622 lines
15 KiB
Markdown
622 lines
15 KiB
Markdown
# 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. 验证系统资源使用情况 |