# 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"} ``` **期望响应**: ```json { "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"} ``` **期望响应**: ```json { "ResultCode": "0005", "ResultMsg": "未找到病人信息" } ``` #### 测试用例 1.3:病人已入院 **测试目的**:验证重复入院的处理 **请求消息**: ``` 00540001H0012024-01-15 10:30:00{"FCode":"3516022344"} ``` **期望响应**: ```json { "ResultCode": "0007", "ResultMsg": "病人已入院" } ``` #### 测试用例 1.4:请求参数错误 **测试目的**:验证错误的JSON格式处理 **请求消息**: ``` 00540001H0012024-01-15 10:30:00{"FCode":} ``` **期望响应**: ```json { "ResultCode": "0009", "ResultMsg": "请求数据格式错误" } ``` ### 2.2 消费额度查询测试(功能码:0002) #### 测试用例 2.1:正常消费额度查询 **测试目的**:验证正常的消费额度查询 **请求消息**: ``` 00540002H0012024-01-15 10:30:00{"FCode":"3516022343"} ``` **期望响应**: ```json { "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"} ``` **期望响应**: ```json { "ResultCode": "0005", "ResultMsg": "未找到病人信息" } ``` ### 2.3 出院处理测试(功能码:0003) #### 测试用例 3.1:正常出院处理 **请求消息**: ``` 00540003H0012024-01-15 10:30:00{"FCode":"3516022343"} ``` **期望响应**: ```json { "ResultCode": "0000", "ResultMsg": "出院处理成功" } ``` #### 测试用例 3.2:病人不存在的出院处理 **请求消息**: ``` 00540003H0012024-01-15 10:30:00{"FCode":"9999999999"} ``` **期望响应**: ```json { "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} ``` **期望响应**: ```json { "ResultCode": "0000", "ResultMsg": "消费记录保存成功" } ``` #### 测试用例 4.2:缺少必填字段的消费记录 **请求消息**: ``` 00540004H0012024-01-15 10:30:00{"FCode":"3516022343"} ``` **期望响应**: ```json { "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"]} ``` **期望响应**: ```json { "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":[]} ``` **期望响应**: ```json { "ResultCode": "0000", "ResultData": [] } ``` ## 3. 异常情况测试 ### 3.1 连接测试 #### 测试用例 7.1:无效的医院编码 **请求消息**: ``` 00540001XXXX2024-01-15 10:30:00{"FCode":"3516022343"} ``` **期望响应**: ```json { "ResultCode": "0009", "ResultMsg": "无效的医院编码" } ``` #### 测试用例 7.2:无效的功能码 **请求消息**: ``` 00549999H0012024-01-15 10:30:00{"FCode":"3516022343"} ``` **期望响应**: ```json { "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 测试脚本 ```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 测试脚本 ```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. 验证系统资源使用情况