HospitalPay-Go/docs/测试用例.md

15 KiB
Raw Blame History

HospitalPay-Go Socket 服务器测试用例

1. 测试环境准备

1.1 服务器配置

  • 服务器地址localhost
  • 服务器端口8080根据配置文件
  • 医院编码H001根据配置文件

1.2 测试工具

  • TCP客户端工具如telnet、nc、自定义客户端
  • 网络抓包工具如Wireshark

2. 基础功能测试

2.1 入院登记测试功能码0001

测试用例 1.1:正常入院登记

测试目的:验证正常病人入院登记功能

请求消息

00540001H0012024-01-15 10:30:00{"FCode":"3516022343"}

期望响应

{
    "ResultCode": "0000",
    "ResultData": {
        "FCode": "3516022343",
        "FName": "测试病人",
        "AmountA": 100.00,
        "AmountB": 50.00,
        "AmountC": 150.00,
        "BankAccNo": "6222021234567890",
        "BankAmount": 1000.00,
        "Fflag": 0,
        "Flimitflag": 0,
        "Flimitamt": 0
    }
}

测试用例 1.2:病人不存在

测试目的:验证查询不存在的病人

请求消息

00540001H0012024-01-15 10:30:00{"FCode":"9999999999"}

期望响应

{
    "ResultCode": "0005",
    "ResultMsg": "未找到病人信息"
}

测试用例 1.3:病人已入院

测试目的:验证重复入院的处理

请求消息

00540001H0012024-01-15 10:30:00{"FCode":"3516022344"}

期望响应

{
    "ResultCode": "0007",
    "ResultMsg": "病人已入院"
}

测试用例 1.4:请求参数错误

测试目的验证错误的JSON格式处理

请求消息

00540001H0012024-01-15 10:30:00{"FCode":}

期望响应

{
    "ResultCode": "0009",
    "ResultMsg": "请求数据格式错误"
}

2.2 消费额度查询测试功能码0002

测试用例 2.1:正常消费额度查询

测试目的:验证正常的消费额度查询

请求消息

00540002H0012024-01-15 10:30:00{"FCode":"3516022343"}

期望响应

{
    "ResultCode": "0000",
    "ResultData": {
        "AmountA": 50.00,
        "AmountB": 30.00,
        "FreeAmountA": 0,
        "FreeAmountB": 0,
        "Checkflag": 0,
        "FCode": "3516022343",
        "FCriminal": "测试病人",
        "Flag": 0
    }
}

测试用例 2.2:病人不存在的消费额度查询

请求消息

00540002H0012024-01-15 10:30:00{"FCode":"9999999999"}

期望响应

{
    "ResultCode": "0005",
    "ResultMsg": "未找到病人信息"
}

2.3 出院处理测试功能码0003

测试用例 3.1:正常出院处理

请求消息

00540003H0012024-01-15 10:30:00{"FCode":"3516022343"}

期望响应

{
    "ResultCode": "0000",
    "ResultMsg": "出院处理成功"
}

测试用例 3.2:病人不存在的出院处理

请求消息

00540003H0012024-01-15 10:30:00{"FCode":"9999999999"}

期望响应

{
    "ResultCode": "0005",
    "ResultMsg": "未找到病人信息"
}

2.4 消费记录测试功能码0004

测试用例 4.1:正常消费记录

请求消息

01840004H0012024-01-15 10:30:00{"FCode":"3516022343","InvoiceNo":"INV20240115001","AmountA":50.00,"AmountB":30.00,"Amount":80.00,"FreeAmountA":0.00,"FreeAmountB":0.00,"CrtDate":"2024-01-15T10:30:00Z","FCriminal":"测试病人","CardCode":"CARD001","OrderId":123456}

期望响应

{
    "ResultCode": "0000",
    "ResultMsg": "消费记录保存成功"
}

测试用例 4.2:缺少必填字段的消费记录

请求消息

00540004H0012024-01-15 10:30:00{"FCode":"3516022343"}

期望响应

{
    "ResultCode": "0009",
    "ResultMsg": "请求数据格式错误"
}

2.5 实时余额查询测试功能码0005

测试用例 5.1:正常实时余额查询

请求消息

00540005H0012024-01-15 10:30:00{"FCode":"3516022343"}

期望响应:与入院登记响应格式相同

2.6 发票同步测试功能码0006

测试用例 6.1:正常发票同步

请求消息

00800006H0012024-01-15 10:30:00{"InvoiceList":["INV001","INV002","INV003"]}

期望响应

{
    "ResultCode": "0000",
    "ResultData": [
        {
            "BankFlag": 2,
            "CAmount": 100.00,
            "FCode": "3516022343",
            "Origid": "INV001",
            "SendDate": "2024-01-15T10:30:00Z"
        },
        {
            "BankFlag": 2,
            "CAmount": 100.00,
            "FCode": "3516022343",
            "Origid": "INV002",
            "SendDate": "2024-01-15T10:30:00Z"
        },
        {
            "BankFlag": 2,
            "CAmount": 100.00,
            "FCode": "3516022343",
            "Origid": "INV003",
            "SendDate": "2024-01-15T10:30:00Z"
        }
    ]
}

测试用例 6.2:空发票列表同步

请求消息

00540006H0012024-01-15 10:30:00{"InvoiceList":[]}

期望响应

{
    "ResultCode": "0000",
    "ResultData": []
}

3. 异常情况测试

3.1 连接测试

测试用例 7.1:无效的医院编码

请求消息

00540001XXXX2024-01-15 10:30:00{"FCode":"3516022343"}

期望响应

{
    "ResultCode": "0009",
    "ResultMsg": "无效的医院编码"
}

测试用例 7.2:无效的功能码

请求消息

00549999H0012024-01-15 10:30:00{"FCode":"3516022343"}

期望响应

{
    "ResultCode": "0008",
    "ResultMsg": "未知的功能码"
}

测试用例 7.3:消息长度不足

请求消息

0001H001

期望行为:连接被关闭,服务器记录错误日志

测试用例 7.4:消息格式错误

请求消息

INVALID_MESSAGE_FORMAT

期望行为:连接被关闭,服务器记录错误日志

3.2 并发测试

测试用例 8.1:最大连接数测试

测试目的:验证服务器的最大连接数限制

测试步骤

  1. 同时建立超过配置的最大连接数的连接
  2. 验证超出限制的连接被拒绝
  3. 检查服务器日志记录

期望结果

  • 在限制内的连接正常处理
  • 超出限制的连接被拒绝
  • 服务器记录相应的警告日志

测试用例 8.2:并发请求测试

测试目的:验证服务器处理并发请求的能力

测试步骤

  1. 同时发送多个不同功能码的请求
  2. 验证所有请求都得到正确响应
  3. 检查响应时间

期望结果

  • 所有请求都得到正确处理
  • 响应时间在可接受范围内
  • 无数据竞争或死锁

3.3 超时测试

测试用例 9.1:读取超时测试

测试步骤

  1. 建立连接但不发送数据
  2. 等待超过配置的读取超时时间

期望结果

  • 连接被服务器主动关闭
  • 服务器记录超时日志

测试用例 9.2:写入超时测试

测试步骤

  1. 发送请求后立即关闭客户端的接收
  2. 服务器尝试发送响应

期望结果

  • 服务器检测到写入超时
  • 连接被正确清理

4. 性能测试

4.1 吞吐量测试

测试用例 10.1:单连接吞吐量

测试目的:测试单个连接的处理能力

测试方法

  • 使用单个连接连续发送1000个请求
  • 记录总处理时间和平均响应时间

性能指标

  • 每秒处理请求数TPS
  • 平均响应时间
  • 95%响应时间

测试用例 10.2:多连接吞吐量

测试目的:测试多连接并发处理能力

测试方法

  • 使用10个并发连接每个连接发送100个请求
  • 记录总处理时间和响应时间分布

4.2 内存和CPU使用率测试

测试用例 11.1:长时间运行测试

测试目的:验证服务器长时间运行的稳定性

测试方法

  • 持续发送请求24小时
  • 监控内存使用率、CPU使用率
  • 检查是否有内存泄漏

5. 测试脚本

5.1 Go 测试脚本

package main

import (
    "fmt"
    "net"
    "time"
    "sync"
    "log"
)

func testConnection(testCase string, message string, expectedCode string) {
    conn, err := net.Dial("tcp", "localhost:8080")
    if err != nil {
        log.Printf("测试用例 %s 失败: 连接错误 %v", testCase, err)
        return
    }
    defer conn.Close()

    // 发送请求
    _, err = conn.Write([]byte(message))
    if err != nil {
        log.Printf("测试用例 %s 失败: 发送错误 %v", testCase, err)
        return
    }

    // 读取响应
    buffer := make([]byte, 4096)
    conn.SetReadDeadline(time.Now().Add(5 * time.Second))
    n, err := conn.Read(buffer)
    if err != nil {
        log.Printf("测试用例 %s 失败: 读取错误 %v", testCase, err)
        return
    }

    response := string(buffer[:n])
    log.Printf("测试用例 %s: 响应 %s", testCase, response)
    
    // 简单验证响应码
    if len(response) > 4 {
        responseData := response[4:]
        if expectedCode != "" && !contains(responseData, expectedCode) {
            log.Printf("测试用例 %s 失败: 期望响应码 %s", testCase, expectedCode)
        } else {
            log.Printf("测试用例 %s 成功", testCase)
        }
    }
}

func contains(s, substr string) bool {
    return len(s) >= len(substr) && s[:len(substr)] == substr
}

func main() {
    // 测试用例
    testCases := []struct {
        name     string
        message  string
        expected string
    }{
        {
            "1.1-正常入院登记",
            "00540001H0012024-01-15 10:30:00{\"FCode\":\"3516022343\"}",
            "\"ResultCode\":\"0000\"",
        },
        {
            "1.2-病人不存在",
            "00540001H0012024-01-15 10:30:00{\"FCode\":\"9999999999\"}",
            "\"ResultCode\":\"0005\"",
        },
        {
            "7.1-无效医院编码",
            "00540001XXXX2024-01-15 10:30:00{\"FCode\":\"3516022343\"}",
            "\"ResultCode\":\"0009\"",
        },
        {
            "7.2-无效功能码",
            "00549999H0012024-01-15 10:30:00{\"FCode\":\"3516022343\"}",
            "\"ResultCode\":\"0008\"",
        },
    }

    for _, tc := range testCases {
        testConnection(tc.name, tc.message, tc.expected)
        time.Sleep(100 * time.Millisecond) // 避免过快请求
    }

    // 并发测试
    log.Println("开始并发测试...")
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            testConnection(
                fmt.Sprintf("并发测试-%d", id),
                "00540001H0012024-01-15 10:30:00{\"FCode\":\"3516022343\"}",
                "\"ResultCode\":\"0000\"",
            )
        }(i)
    }
    wg.Wait()
    log.Println("并发测试完成")
}

5.2 Python 测试脚本

import socket
import json
import time
import threading
from concurrent.futures import ThreadPoolExecutor

def send_request(test_name, message, expected_code=None):
    """发送测试请求"""
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(5)
        sock.connect(('localhost', 8080))
        
        # 发送请求
        sock.send(message.encode('utf-8'))
        
        # 接收响应
        response = sock.recv(4096).decode('utf-8')
        
        print(f"测试用例 {test_name}: 响应 {response}")
        
        # 验证响应码
        if expected_code and len(response) > 4:
            response_data = response[4:]
            if expected_code in response_data:
                print(f"测试用例 {test_name} 成功")
            else:
                print(f"测试用例 {test_name} 失败: 期望响应码 {expected_code}")
        
        sock.close()
        return True
        
    except Exception as e:
        print(f"测试用例 {test_name} 失败: {e}")
        return False

def run_basic_tests():
    """运行基础功能测试"""
    test_cases = [
        {
            'name': '1.1-正常入院登记',
            'message': '00540001H0012024-01-15 10:30:00{"FCode":"3516022343"}',
            'expected': '"ResultCode":"0000"'
        },
        {
            'name': '1.2-病人不存在',
            'message': '00540001H0012024-01-15 10:30:00{"FCode":"9999999999"}',
            'expected': '"ResultCode":"0005"'
        },
        {
            'name': '2.1-正常消费额度查询',
            'message': '00540002H0012024-01-15 10:30:00{"FCode":"3516022343"}',
            'expected': '"ResultCode":"0000"'
        },
        {
            'name': '7.1-无效医院编码',
            'message': '00540001XXXX2024-01-15 10:30:00{"FCode":"3516022343"}',
            'expected': '"ResultCode":"0009"'
        },
    ]
    
    for test_case in test_cases:
        send_request(test_case['name'], test_case['message'], test_case['expected'])
        time.sleep(0.1)  # 避免过快请求

def run_concurrent_tests():
    """运行并发测试"""
    print("开始并发测试...")
    
    def concurrent_request(thread_id):
        return send_request(
            f'并发测试-{thread_id}',
            '00540001H0012024-01-15 10:30:00{"FCode":"3516022343"}',
            '"ResultCode":"0000"'
        )
    
    with ThreadPoolExecutor(max_workers=10) as executor:
        futures = [executor.submit(concurrent_request, i) for i in range(10)]
        results = [future.result() for future in futures]
    
    success_count = sum(results)
    print(f"并发测试完成: {success_count}/10 成功")

if __name__ == "__main__":
    print("开始基础功能测试...")
    run_basic_tests()
    
    print("\n开始并发测试...")
    run_concurrent_tests()
    
    print("\n所有测试完成")

6. 测试报告模板

6.1 测试执行记录

测试用例 执行时间 执行结果 响应时间 备注
1.1-正常入院登记 2024-01-15 10:30:00 通过 50ms -
1.2-病人不存在 2024-01-15 10:30:05 通过 45ms -
7.1-无效医院编码 2024-01-15 10:30:10 通过 30ms -

6.2 性能测试结果

测试项目 测试结果 标准值 是否通过
单连接TPS 1000 req/s >500 req/s 通过
平均响应时间 50ms <100ms 通过
95%响应时间 80ms <200ms 通过
最大并发连接 100 100 通过

6.3 问题记录

问题编号 问题描述 严重程度 状态 备注
BUG-001 某种情况下响应超时 已修复 -

7. 测试环境清理

测试完成后需要:

  1. 清理测试数据
  2. 重置数据库状态
  3. 检查服务器日志
  4. 验证系统资源使用情况