doc:添加项目文档
This commit is contained in:
parent
b551b4016c
commit
77650de0f2
378
docs/API接口文档.md
Normal file
378
docs/API接口文档.md
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
# HospitalPay-Go Socket 服务器接口文档
|
||||||
|
|
||||||
|
## 1. 概述
|
||||||
|
|
||||||
|
HospitalPay-Go Socket 服务器是一个基于TCP协议的医院支付系统服务器,提供病人入院、出院、消费记录、余额查询等功能。
|
||||||
|
|
||||||
|
### 1.1 服务器信息
|
||||||
|
- **协议**: TCP Socket
|
||||||
|
- **端口**: 配置文件中指定
|
||||||
|
- **编码**: UTF-8
|
||||||
|
- **数据格式**: JSON
|
||||||
|
|
||||||
|
### 1.2 消息格式
|
||||||
|
|
||||||
|
所有请求和响应都遵循以下格式:
|
||||||
|
|
||||||
|
```
|
||||||
|
[长度(4位)][功能码(4位)][医院编码(4位)][时间戳(19位)][JSON数据]
|
||||||
|
```
|
||||||
|
|
||||||
|
- **长度**: 4位数字,表示整个消息的长度
|
||||||
|
- **功能码**: 4位数字,标识请求的功能类型
|
||||||
|
- **医院编码**: 4位字符,医院标识码
|
||||||
|
- **时间戳**: 19位时间戳,格式为 `yyyy-MM-dd HH:mm:ss`
|
||||||
|
- **JSON数据**: 具体的请求或响应数据
|
||||||
|
|
||||||
|
### 1.3 响应格式
|
||||||
|
|
||||||
|
所有响应都包含以下基础结构:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ResultCode": "string", // 结果代码
|
||||||
|
"ResultData": object, // 响应数据(可选)
|
||||||
|
"ResultMsg": "string" // 结果消息(可选)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. 错误码说明
|
||||||
|
|
||||||
|
| 错误码 | 说明 |
|
||||||
|
|--------|------|
|
||||||
|
| 0000 | 成功 |
|
||||||
|
| 0005 | 未找到病人信息 |
|
||||||
|
| 0006 | 入院处理失败 |
|
||||||
|
| 0007 | 病人已入院 |
|
||||||
|
| 0008 | 系统异常 |
|
||||||
|
| 0009 | 请求参数错误 |
|
||||||
|
| 1001 | 出院处理失败 |
|
||||||
|
| 1002 | 消费额度查询失败 |
|
||||||
|
| 1003 | 消费记录保存失败 |
|
||||||
|
| 1004 | 实时余额查询失败 |
|
||||||
|
| 1005 | 发票同步失败 |
|
||||||
|
|
||||||
|
## 3. 接口详情
|
||||||
|
|
||||||
|
### 3.1 入院登记
|
||||||
|
|
||||||
|
**功能码**: `0001`
|
||||||
|
|
||||||
|
**功能说明**: 病人入院时的登记处理
|
||||||
|
|
||||||
|
**请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"FCode": "string" // 病人编号,必填
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ResultCode": "0000",
|
||||||
|
"ResultData": {
|
||||||
|
"FCode": "string", // 病人编号
|
||||||
|
"FName": "string", // 病人姓名
|
||||||
|
"AmountA": 100.00, // A类金额
|
||||||
|
"AmountB": 50.00, // B类金额
|
||||||
|
"AmountC": 150.00, // C类金额
|
||||||
|
"BankAccNo": "string", // 银行账号
|
||||||
|
"BankAmount": 1000.00, // 银行余额
|
||||||
|
"Fflag": 0, // 状态标志 (0:正常, 1:已入院)
|
||||||
|
"Flimitflag": 0, // 限制标志
|
||||||
|
"Flimitamt": 0.00 // 限制金额
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**:
|
||||||
|
```
|
||||||
|
请求: 0001{"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}}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 消费额度查询
|
||||||
|
|
||||||
|
**功能码**: `0002`
|
||||||
|
|
||||||
|
**功能说明**: 查询病人当月消费额度信息
|
||||||
|
|
||||||
|
**请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"FCode": "string" // 病人编号,必填
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ResultCode": "0000",
|
||||||
|
"ResultData": {
|
||||||
|
"AmountA": 50.00, // A类消费金额
|
||||||
|
"AmountB": 30.00, // B类消费金额
|
||||||
|
"FreeAmountA": 0.00, // A类可用金额
|
||||||
|
"FreeAmountB": 0.00, // B类可用金额
|
||||||
|
"Checkflag": 0, // 检查标志
|
||||||
|
"FCode": "string", // 病人编号
|
||||||
|
"FCriminal": "string", // 病人姓名
|
||||||
|
"Flag": 0 // 状态标志
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.3 出院处理
|
||||||
|
|
||||||
|
**功能码**: `0003`
|
||||||
|
|
||||||
|
**功能说明**: 病人出院时的处理
|
||||||
|
|
||||||
|
**请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"FCode": "string" // 病人编号,必填
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ResultCode": "0000",
|
||||||
|
"ResultMsg": "出院处理成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.4 消费记录
|
||||||
|
|
||||||
|
**功能码**: `0004`
|
||||||
|
|
||||||
|
**功能说明**: 记录病人消费信息
|
||||||
|
|
||||||
|
**请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"FCode": "string", // 病人编号,必填
|
||||||
|
"InvoiceNo": "string", // 发票号,必填
|
||||||
|
"AmountA": 50.00, // A类金额
|
||||||
|
"AmountB": 30.00, // B类金额
|
||||||
|
"Amount": 80.00, // 总金额
|
||||||
|
"FreeAmountA": 0.00, // A类可用金额
|
||||||
|
"FreeAmountB": 0.00, // B类可用金额
|
||||||
|
"CrtDate": "2024-01-01T10:00:00Z", // 创建日期
|
||||||
|
"FCriminal": "string", // 病人姓名
|
||||||
|
"CardCode": "string", // 卡号
|
||||||
|
"OrderId": 123456 // 订单ID
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ResultCode": "0000",
|
||||||
|
"ResultMsg": "消费记录保存成功"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.5 实时余额查询
|
||||||
|
|
||||||
|
**功能码**: `0005`
|
||||||
|
|
||||||
|
**功能说明**: 查询病人实时余额信息
|
||||||
|
|
||||||
|
**请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"FCode": "string" // 病人编号,必填
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应参数**: 与入院登记响应格式相同
|
||||||
|
|
||||||
|
### 3.6 发票同步
|
||||||
|
|
||||||
|
**功能码**: `0006`
|
||||||
|
|
||||||
|
**功能说明**: 同步发票信息到系统
|
||||||
|
|
||||||
|
**请求参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"InvoiceList": [
|
||||||
|
"INV001",
|
||||||
|
"INV002",
|
||||||
|
"INV003"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**响应参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"ResultCode": "0000",
|
||||||
|
"ResultData": [
|
||||||
|
{
|
||||||
|
"BankFlag": 2, // 银行标志
|
||||||
|
"CAmount": 100.00, // 金额
|
||||||
|
"FCode": "3516022343", // 病人编号
|
||||||
|
"Origid": "INV001", // 原始发票号
|
||||||
|
"SendDate": "2024-01-01T10:00:00Z" // 发送日期
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. 连接管理
|
||||||
|
|
||||||
|
### 4.1 连接限制
|
||||||
|
- 最大并发连接数:配置文件中指定
|
||||||
|
- 连接超时时间:配置文件中指定
|
||||||
|
- 读取超时时间:配置文件中指定
|
||||||
|
- 写入超时时间:配置文件中指定
|
||||||
|
|
||||||
|
### 4.2 连接流程
|
||||||
|
1. 客户端建立TCP连接
|
||||||
|
2. 发送请求消息(按照消息格式)
|
||||||
|
3. 服务器验证医院编码
|
||||||
|
4. 处理业务逻辑
|
||||||
|
5. 返回响应消息
|
||||||
|
6. 关闭连接
|
||||||
|
|
||||||
|
## 5. 安全说明
|
||||||
|
|
||||||
|
### 5.1 医院编码验证
|
||||||
|
所有请求必须包含正确的医院编码,否则返回"无效的医院编码"错误。
|
||||||
|
|
||||||
|
### 5.2 超时控制
|
||||||
|
- 连接建立后有读取超时限制
|
||||||
|
- 响应发送有写入超时限制
|
||||||
|
- 业务处理有上下文超时控制(10秒)
|
||||||
|
|
||||||
|
## 6. 监控指标
|
||||||
|
|
||||||
|
系统提供以下监控指标:
|
||||||
|
- 活跃连接数
|
||||||
|
- 请求计数(按功能码分类)
|
||||||
|
- 请求处理时间(按功能码分类)
|
||||||
|
- 错误计数(按功能码和错误码分类)
|
||||||
|
|
||||||
|
## 7. 示例代码
|
||||||
|
|
||||||
|
### 7.1 Go 客户端示例
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
conn, err := net.Dial("tcp", "localhost:8080")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
// 构造请求消息
|
||||||
|
functionCode := "0001"
|
||||||
|
hospitalCode := "H001"
|
||||||
|
timestamp := time.Now().Format("2006-01-02 15:04:05")
|
||||||
|
data := `{"FCode":"3516022343"}`
|
||||||
|
|
||||||
|
message := fmt.Sprintf("%s%s%s%s", functionCode, hospitalCode, timestamp, data)
|
||||||
|
fullMessage := fmt.Sprintf("%04d%s", len(message), message)
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
_, err = conn.Write([]byte(fullMessage))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取响应
|
||||||
|
buffer := make([]byte, 4096)
|
||||||
|
n, err := conn.Read(buffer)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
response := string(buffer[:n])
|
||||||
|
fmt.Printf("Response: %s\n", response)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.2 Python 客户端示例
|
||||||
|
|
||||||
|
```python
|
||||||
|
import socket
|
||||||
|
import json
|
||||||
|
import time
|
||||||
|
|
||||||
|
def send_request(host, port, function_code, hospital_code, data):
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
try:
|
||||||
|
sock.connect((host, port))
|
||||||
|
|
||||||
|
# 构造消息
|
||||||
|
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
json_data = json.dumps(data)
|
||||||
|
message = f"{function_code}{hospital_code}{timestamp}{json_data}"
|
||||||
|
full_message = f"{len(message):04d}{message}"
|
||||||
|
|
||||||
|
# 发送请求
|
||||||
|
sock.send(full_message.encode('utf-8'))
|
||||||
|
|
||||||
|
# 接收响应
|
||||||
|
response = sock.recv(4096).decode('utf-8')
|
||||||
|
|
||||||
|
# 解析响应
|
||||||
|
length = int(response[:4])
|
||||||
|
json_response = response[4:4+length]
|
||||||
|
|
||||||
|
return json.loads(json_response)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
# 使用示例
|
||||||
|
if __name__ == "__main__":
|
||||||
|
result = send_request(
|
||||||
|
"localhost", 8080,
|
||||||
|
"0001", "H001",
|
||||||
|
{"FCode": "3516022343"}
|
||||||
|
)
|
||||||
|
print(json.dumps(result, indent=2, ensure_ascii=False))
|
||||||
|
```
|
||||||
|
|
||||||
|
## 8. 常见问题
|
||||||
|
|
||||||
|
### 8.1 连接被拒绝
|
||||||
|
- 检查服务器是否启动
|
||||||
|
- 检查端口是否正确
|
||||||
|
- 检查是否达到最大连接数限制
|
||||||
|
|
||||||
|
### 8.2 医院编码错误
|
||||||
|
- 确认医院编码配置正确
|
||||||
|
- 检查请求消息格式是否正确
|
||||||
|
|
||||||
|
### 8.3 请求超时
|
||||||
|
- 检查网络连接
|
||||||
|
- 确认服务器负载情况
|
||||||
|
- 检查请求数据格式是否正确
|
||||||
|
|
||||||
|
### 8.4 数据格式错误
|
||||||
|
- 确认JSON格式正确
|
||||||
|
- 检查必填字段是否完整
|
||||||
|
- 验证数据类型是否匹配
|
||||||
|
|
||||||
|
## 9. 版本历史
|
||||||
|
|
||||||
|
| 版本 | 日期 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 1.0.0 | 2024-01-01 | 初始版本,支持基础的6个功能接口 |
|
||||||
|
|
||||||
|
## 10. 联系方式
|
||||||
|
|
||||||
|
如有问题请联系开发团队。
|
||||||
105
docs/README.md
Normal file
105
docs/README.md
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
# HospitalPay-Go 接口文档
|
||||||
|
|
||||||
|
欢迎使用 HospitalPay-Go Socket 服务器接口文档。本文档提供了完整的API接口说明、测试用例和快速参考。
|
||||||
|
|
||||||
|
## 📚 文档目录
|
||||||
|
|
||||||
|
### 1. [API接口文档](./API接口文档.md)
|
||||||
|
**完整的接口规范文档**
|
||||||
|
- 服务器概述和消息格式
|
||||||
|
- 详细的接口说明(6个功能接口)
|
||||||
|
- 错误码说明
|
||||||
|
- 连接管理和安全说明
|
||||||
|
- 监控指标
|
||||||
|
- 客户端示例代码(Go/Python)
|
||||||
|
- 常见问题解答
|
||||||
|
|
||||||
|
### 2. [测试用例](./测试用例.md)
|
||||||
|
**全面的测试用例文档**
|
||||||
|
- 基础功能测试(每个接口的正常和异常情况)
|
||||||
|
- 异常情况测试(连接、并发、超时)
|
||||||
|
- 性能测试(吞吐量、内存、CPU)
|
||||||
|
- 测试脚本(Go/Python)
|
||||||
|
- 测试报告模板
|
||||||
|
|
||||||
|
### 3. [快速参考](./快速参考.md)
|
||||||
|
**开发者快速查阅手册**
|
||||||
|
- 消息格式和功能码列表
|
||||||
|
- 错误码速查表
|
||||||
|
- 数据结构定义
|
||||||
|
- 快速示例
|
||||||
|
- 客户端代码模板
|
||||||
|
|
||||||
|
## 🚀 快速开始
|
||||||
|
|
||||||
|
### 服务器信息
|
||||||
|
- **协议**: TCP Socket
|
||||||
|
- **端口**: 配置文件中指定(默认8080)
|
||||||
|
- **编码**: UTF-8
|
||||||
|
- **数据格式**: JSON
|
||||||
|
|
||||||
|
### 消息格式
|
||||||
|
```
|
||||||
|
[长度(4位)][功能码(4位)][医院编码(4位)][时间戳(19位)][JSON数据]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 支持的功能
|
||||||
|
| 功能码 | 功能名称 | 说明 |
|
||||||
|
|--------|----------|------|
|
||||||
|
| 0001 | 入院登记 | 病人入院时的登记处理 |
|
||||||
|
| 0002 | 消费额度查询 | 查询病人当月消费额度 |
|
||||||
|
| 0003 | 出院处理 | 病人出院时的处理 |
|
||||||
|
| 0004 | 消费记录 | 记录病人消费信息 |
|
||||||
|
| 0005 | 实时余额查询 | 查询病人实时余额 |
|
||||||
|
| 0006 | 发票同步 | 同步发票信息到系统 |
|
||||||
|
|
||||||
|
## 🔧 开发指南
|
||||||
|
|
||||||
|
### 1. 环境准备
|
||||||
|
确保服务器已启动并配置正确的端口和医院编码。
|
||||||
|
|
||||||
|
### 2. 客户端开发
|
||||||
|
参考 [API接口文档](./API接口文档.md) 中的示例代码,或使用 [快速参考](./快速参考.md) 中的代码模板。
|
||||||
|
|
||||||
|
### 3. 测试验证
|
||||||
|
使用 [测试用例](./测试用例.md) 中的测试脚本验证功能是否正常。
|
||||||
|
|
||||||
|
## 📋 示例请求
|
||||||
|
|
||||||
|
### 入院登记示例
|
||||||
|
```
|
||||||
|
请求: 00540001H0012024-01-15 10:30:00{"FCode":"3516022343"}
|
||||||
|
响应: {"ResultCode":"0000","ResultData":{"FCode":"3516022343","FName":"测试病人",...}}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 消费记录示例
|
||||||
|
```
|
||||||
|
请求: 01840004H0012024-01-15 10:30:00{"FCode":"3516022343","InvoiceNo":"INV001",...}
|
||||||
|
响应: {"ResultCode":"0000","ResultMsg":"消费记录保存成功"}
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚠️ 重要提醒
|
||||||
|
|
||||||
|
1. **医院编码验证**: 所有请求必须包含正确的医院编码
|
||||||
|
2. **消息格式**: 严格按照指定格式构造消息
|
||||||
|
3. **超时控制**: 注意连接和处理超时时间
|
||||||
|
4. **错误处理**: 根据错误码进行相应的错误处理
|
||||||
|
|
||||||
|
## 🐛 问题反馈
|
||||||
|
|
||||||
|
如果在使用过程中遇到问题:
|
||||||
|
|
||||||
|
1. 首先查阅 [API接口文档](./API接口文档.md) 中的"常见问题"部分
|
||||||
|
2. 使用 [测试用例](./测试用例.md) 中的测试脚本进行验证
|
||||||
|
3. 检查服务器日志和网络连接
|
||||||
|
4. 联系开发团队获取支持
|
||||||
|
|
||||||
|
## 📖 文档版本
|
||||||
|
|
||||||
|
| 版本 | 日期 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| 1.0.0 | 2024-01-15 | 初始版本,包含6个基础功能接口 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**注意**: 本文档基于当前代码版本生成,如有更新请及时同步文档内容。
|
||||||
167
docs/快速参考.md
Normal file
167
docs/快速参考.md
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
# HospitalPay-Go Socket 接口快速参考
|
||||||
|
|
||||||
|
## 消息格式
|
||||||
|
```
|
||||||
|
[长度(4位)][功能码(4位)][医院编码(4位)][时间戳(19位)][JSON数据]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 功能码列表
|
||||||
|
|
||||||
|
| 功能码 | 功能名称 | 请求参数 | 响应数据 |
|
||||||
|
|--------|----------|----------|----------|
|
||||||
|
| 0001 | 入院登记 | `{"FCode":"string"}` | CriminalInfo |
|
||||||
|
| 0002 | 消费额度查询 | `{"FCode":"string"}` | ConsumeQuota |
|
||||||
|
| 0003 | 出院处理 | `{"FCode":"string"}` | 成功消息 |
|
||||||
|
| 0004 | 消费记录 | ConsumeRecord | 成功消息 |
|
||||||
|
| 0005 | 实时余额查询 | `{"FCode":"string"}` | CriminalInfo |
|
||||||
|
| 0006 | 发票同步 | `{"InvoiceList":["string"]}` | InvoiceSyncResult[] |
|
||||||
|
|
||||||
|
## 错误码
|
||||||
|
|
||||||
|
| 错误码 | 说明 |
|
||||||
|
|--------|------|
|
||||||
|
| 0000 | 成功 |
|
||||||
|
| 0005 | 未找到病人信息 |
|
||||||
|
| 0006 | 入院处理失败 |
|
||||||
|
| 0007 | 病人已入院 |
|
||||||
|
| 0008 | 系统异常 |
|
||||||
|
| 0009 | 请求参数错误 |
|
||||||
|
|
||||||
|
## 数据结构
|
||||||
|
|
||||||
|
### CriminalInfo (病人信息)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"FCode": "string", // 病人编号
|
||||||
|
"FName": "string", // 病人姓名
|
||||||
|
"AmountA": 100.00, // A类金额
|
||||||
|
"AmountB": 50.00, // B类金额
|
||||||
|
"AmountC": 150.00, // C类金额
|
||||||
|
"BankAccNo": "string", // 银行账号
|
||||||
|
"BankAmount": 1000.00, // 银行余额
|
||||||
|
"Fflag": 0, // 状态标志
|
||||||
|
"Flimitflag": 0, // 限制标志
|
||||||
|
"Flimitamt": 0.00 // 限制金额
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ConsumeQuota (消费额度)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"AmountA": 50.00, // A类消费金额
|
||||||
|
"AmountB": 30.00, // B类消费金额
|
||||||
|
"FreeAmountA": 0.00, // A类可用金额
|
||||||
|
"FreeAmountB": 0.00, // B类可用金额
|
||||||
|
"Checkflag": 0, // 检查标志
|
||||||
|
"FCode": "string", // 病人编号
|
||||||
|
"FCriminal": "string", // 病人姓名
|
||||||
|
"Flag": 0 // 状态标志
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ConsumeRecord (消费记录)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"FCode": "string", // 病人编号
|
||||||
|
"InvoiceNo": "string", // 发票号
|
||||||
|
"AmountA": 50.00, // A类金额
|
||||||
|
"AmountB": 30.00, // B类金额
|
||||||
|
"Amount": 80.00, // 总金额
|
||||||
|
"FreeAmountA": 0.00, // A类可用金额
|
||||||
|
"FreeAmountB": 0.00, // B类可用金额
|
||||||
|
"CrtDate": "2024-01-01T10:00:00Z", // 创建日期
|
||||||
|
"FCriminal": "string", // 病人姓名
|
||||||
|
"CardCode": "string", // 卡号
|
||||||
|
"OrderId": 123456 // 订单ID
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### InvoiceSyncResult (发票同步结果)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"BankFlag": 2, // 银行标志
|
||||||
|
"CAmount": 100.00, // 金额
|
||||||
|
"FCode": "3516022343", // 病人编号
|
||||||
|
"Origid": "INV001", // 原始发票号
|
||||||
|
"SendDate": "2024-01-01T10:00:00Z" // 发送日期
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 快速示例
|
||||||
|
|
||||||
|
### 入院登记
|
||||||
|
```
|
||||||
|
请求: 00540001H0012024-01-15 10:30:00{"FCode":"3516022343"}
|
||||||
|
响应: {"ResultCode":"0000","ResultData":{...}}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 消费记录
|
||||||
|
```
|
||||||
|
请求: 01840004H0012024-01-15 10:30:00{"FCode":"3516022343","InvoiceNo":"INV001","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":"消费记录保存成功"}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 发票同步
|
||||||
|
```
|
||||||
|
请求: 00800006H0012024-01-15 10:30:00{"InvoiceList":["INV001","INV002"]}
|
||||||
|
响应: {"ResultCode":"0000","ResultData":[...]}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 客户端代码模板
|
||||||
|
|
||||||
|
### Go 客户端
|
||||||
|
```go
|
||||||
|
func sendRequest(functionCode, hospitalCode, data string) (string, error) {
|
||||||
|
conn, err := net.Dial("tcp", "localhost:8080")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
timestamp := time.Now().Format("2006-01-02 15:04:05")
|
||||||
|
message := fmt.Sprintf("%s%s%s%s", functionCode, hospitalCode, timestamp, data)
|
||||||
|
fullMessage := fmt.Sprintf("%04d%s", len(message), message)
|
||||||
|
|
||||||
|
_, err = conn.Write([]byte(fullMessage))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := make([]byte, 4096)
|
||||||
|
n, err := conn.Read(buffer)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(buffer[:n]), nil
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python 客户端
|
||||||
|
```python
|
||||||
|
def send_request(function_code, hospital_code, data):
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
try:
|
||||||
|
sock.connect(('localhost', 8080))
|
||||||
|
|
||||||
|
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
json_data = json.dumps(data)
|
||||||
|
message = f"{function_code}{hospital_code}{timestamp}{json_data}"
|
||||||
|
full_message = f"{len(message):04d}{message}"
|
||||||
|
|
||||||
|
sock.send(full_message.encode('utf-8'))
|
||||||
|
response = sock.recv(4096).decode('utf-8')
|
||||||
|
|
||||||
|
length = int(response[:4])
|
||||||
|
json_response = response[4:4+length]
|
||||||
|
return json.loads(json_response)
|
||||||
|
finally:
|
||||||
|
sock.close()
|
||||||
|
```
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
1. **连接被拒绝**: 检查服务器状态和端口
|
||||||
|
2. **医院编码错误**: 确认配置文件中的医院编码
|
||||||
|
3. **消息格式错误**: 检查长度计算和JSON格式
|
||||||
|
4. **超时**: 检查网络连接和服务器负载
|
||||||
622
docs/测试用例.md
Normal file
622
docs/测试用例.md
Normal file
@ -0,0 +1,622 @@
|
|||||||
|
# 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. 验证系统资源使用情况
|
||||||
Loading…
x
Reference in New Issue
Block a user