415 lines
13 KiB
Python
415 lines
13 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
# -*- coding: utf-8 -*-
|
|||
|
|
"""
|
|||
|
|
陪诊系统后台API接口测试脚本
|
|||
|
|
支持更详细的测试和结果输出
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import requests
|
|||
|
|
import json
|
|||
|
|
import sys
|
|||
|
|
from datetime import datetime
|
|||
|
|
from typing import Dict, Optional
|
|||
|
|
|
|||
|
|
# 服务器地址配置
|
|||
|
|
# 默认使用公网地址,如果无法访问会自动尝试本地地址
|
|||
|
|
SERVER_URL = "http://101.43.95.130:8039"
|
|||
|
|
LOCAL_URL = "http://localhost:8039"
|
|||
|
|
|
|||
|
|
# 测试结果统计
|
|||
|
|
class TestResult:
|
|||
|
|
def __init__(self):
|
|||
|
|
self.total = 0
|
|||
|
|
self.passed = 0
|
|||
|
|
self.failed = 0
|
|||
|
|
self.results = []
|
|||
|
|
|
|||
|
|
# 颜色输出
|
|||
|
|
class Colors:
|
|||
|
|
GREEN = '\033[0;32m'
|
|||
|
|
RED = '\033[0;31m'
|
|||
|
|
YELLOW = '\033[1;33m'
|
|||
|
|
BLUE = '\033[0;34m'
|
|||
|
|
NC = '\033[0m' # No Color
|
|||
|
|
|
|||
|
|
def print_colored(text, color=Colors.NC):
|
|||
|
|
"""打印带颜色的文本"""
|
|||
|
|
print(f"{color}{text}{Colors.NC}")
|
|||
|
|
|
|||
|
|
def test_api(name: str, method: str, url: str,
|
|||
|
|
data: Optional[Dict] = None,
|
|||
|
|
headers: Optional[Dict] = None,
|
|||
|
|
expected_status: list = [200, 401, 403]) -> tuple:
|
|||
|
|
"""
|
|||
|
|
测试API接口
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
name: 接口名称
|
|||
|
|
method: 请求方法 (GET/POST)
|
|||
|
|
url: 接口URL
|
|||
|
|
data: 请求数据(POST用)
|
|||
|
|
headers: 请求头
|
|||
|
|
expected_status: 期望的HTTP状态码列表
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
(success: bool, status_code: int, response: dict)
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
if headers is None:
|
|||
|
|
headers = {"Content-Type": "application/json"}
|
|||
|
|
|
|||
|
|
if method.upper() == "GET":
|
|||
|
|
response = requests.get(url, headers=headers, timeout=10)
|
|||
|
|
else:
|
|||
|
|
response = requests.post(url, json=data, headers=headers, timeout=10)
|
|||
|
|
|
|||
|
|
status_code = response.status_code
|
|||
|
|
success = status_code in expected_status
|
|||
|
|
|
|||
|
|
# 尝试解析JSON响应
|
|||
|
|
try:
|
|||
|
|
response_data = response.json()
|
|||
|
|
except:
|
|||
|
|
response_data = {"raw": response.text[:200]}
|
|||
|
|
|
|||
|
|
return success, status_code, response_data
|
|||
|
|
|
|||
|
|
except requests.exceptions.ConnectionError:
|
|||
|
|
return False, 0, {"error": "连接失败,无法访问服务器"}
|
|||
|
|
except requests.exceptions.Timeout:
|
|||
|
|
return False, 0, {"error": "请求超时"}
|
|||
|
|
except Exception as e:
|
|||
|
|
return False, 0, {"error": str(e)}
|
|||
|
|
|
|||
|
|
def check_server_available(url):
|
|||
|
|
"""检查服务器是否可用"""
|
|||
|
|
try:
|
|||
|
|
response = requests.get(f"{url}/", timeout=3)
|
|||
|
|
return True, response.status_code
|
|||
|
|
except:
|
|||
|
|
return False, 0
|
|||
|
|
|
|||
|
|
def run_tests():
|
|||
|
|
"""运行所有测试"""
|
|||
|
|
result = TestResult()
|
|||
|
|
|
|||
|
|
# 自动检测可用的服务器地址
|
|||
|
|
global SERVER_URL
|
|||
|
|
print("正在检测服务器地址...")
|
|||
|
|
server_available, status = check_server_available(SERVER_URL)
|
|||
|
|
if not server_available:
|
|||
|
|
print_colored(f"公网地址 {SERVER_URL} 无法访问,尝试本地地址...", Colors.YELLOW)
|
|||
|
|
local_available, _ = check_server_available(LOCAL_URL)
|
|||
|
|
if local_available:
|
|||
|
|
SERVER_URL = LOCAL_URL
|
|||
|
|
print_colored(f"使用本地地址: {SERVER_URL}", Colors.GREEN)
|
|||
|
|
else:
|
|||
|
|
print_colored("本地地址也无法访问,请检查服务是否运行", Colors.RED)
|
|||
|
|
return 1
|
|||
|
|
|
|||
|
|
print("=" * 60)
|
|||
|
|
print_colored("陪诊系统后台API接口测试", Colors.BLUE)
|
|||
|
|
print("=" * 60)
|
|||
|
|
print(f"服务器地址: {SERVER_URL}")
|
|||
|
|
print(f"开始时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
# 测试用例列表
|
|||
|
|
test_cases = [
|
|||
|
|
# 基础接口(无需认证)
|
|||
|
|
{
|
|||
|
|
"name": "首页接口",
|
|||
|
|
"method": "GET",
|
|||
|
|
"url": f"{SERVER_URL}/",
|
|||
|
|
"data": None,
|
|||
|
|
"headers": None
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "验证码接口",
|
|||
|
|
"method": "GET",
|
|||
|
|
"url": f"{SERVER_URL}/captchaImage",
|
|||
|
|
"data": None,
|
|||
|
|
"headers": None
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
# 登录相关接口
|
|||
|
|
{
|
|||
|
|
"name": "微信登录接口",
|
|||
|
|
"method": "POST",
|
|||
|
|
"url": f"{SERVER_URL}/weixinLogin",
|
|||
|
|
"data": {
|
|||
|
|
"wxcode": "test_code",
|
|||
|
|
"encryptedData": "test_data",
|
|||
|
|
"iv": "test_iv"
|
|||
|
|
},
|
|||
|
|
"headers": {"Content-Type": "application/x-www-form-urlencoded"}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "获取用户Token接口",
|
|||
|
|
"method": "GET",
|
|||
|
|
"url": f"{SERVER_URL}/getUserToken",
|
|||
|
|
"data": {"phonenumber": "13800138000"},
|
|||
|
|
"headers": None
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
# 系统配置接口(需要认证)
|
|||
|
|
{
|
|||
|
|
"name": "价格配置接口",
|
|||
|
|
"method": "GET",
|
|||
|
|
"url": f"{SERVER_URL}/system/config/configKey/price",
|
|||
|
|
"data": None,
|
|||
|
|
"headers": {"Authorization": "Bearer test_token"}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "价格类型配置接口",
|
|||
|
|
"method": "GET",
|
|||
|
|
"url": f"{SERVER_URL}/system/config/configKey/priceType",
|
|||
|
|
"data": None,
|
|||
|
|
"headers": {"Authorization": "Bearer test_token"}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
# 医院相关接口
|
|||
|
|
{
|
|||
|
|
"name": "医院列表接口",
|
|||
|
|
"method": "GET",
|
|||
|
|
"url": f"{SERVER_URL}/system/hospital/list",
|
|||
|
|
"data": None,
|
|||
|
|
"headers": {"Authorization": "Bearer test_token"}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
# 订单相关接口(需要认证)
|
|||
|
|
{
|
|||
|
|
"name": "订单列表接口",
|
|||
|
|
"method": "GET",
|
|||
|
|
"url": f"{SERVER_URL}/system/view/list",
|
|||
|
|
"data": None,
|
|||
|
|
"headers": {"Authorization": "Bearer test_token"}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "创建订单接口",
|
|||
|
|
"method": "POST",
|
|||
|
|
"url": f"{SERVER_URL}/system/order/insertOrderPz",
|
|||
|
|
"data": {
|
|||
|
|
"bId": 104,
|
|||
|
|
"cId": 1,
|
|||
|
|
"yuguMoney": "200",
|
|||
|
|
"yuliu9": "2",
|
|||
|
|
"yuliu10": "1",
|
|||
|
|
"hospitalId": 1,
|
|||
|
|
"startTime": "2024-01-01",
|
|||
|
|
"yuliu11": "13800138000"
|
|||
|
|
},
|
|||
|
|
"headers": {"Authorization": "Bearer test_token"}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
# 用户相关接口(需要认证)
|
|||
|
|
{
|
|||
|
|
"name": "用户列表接口",
|
|||
|
|
"method": "GET",
|
|||
|
|
"url": f"{SERVER_URL}/system/user/list",
|
|||
|
|
"data": None,
|
|||
|
|
"headers": {"Authorization": "Bearer test_token"}
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "获取用户信息接口",
|
|||
|
|
"method": "GET",
|
|||
|
|
"url": f"{SERVER_URL}/getInfo",
|
|||
|
|
"data": None,
|
|||
|
|
"headers": {"Authorization": "Bearer test_token"}
|
|||
|
|
},
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# 执行测试
|
|||
|
|
print("-" * 60)
|
|||
|
|
print_colored("1. 基础接口测试(无需认证)", Colors.YELLOW)
|
|||
|
|
print("-" * 60)
|
|||
|
|
|
|||
|
|
for i, test in enumerate(test_cases[:2], 1):
|
|||
|
|
result.total += 1
|
|||
|
|
print(f"测试 {result.total}: {test['name']} ... ", end="", flush=True)
|
|||
|
|
|
|||
|
|
success, status_code, response_data = test_api(
|
|||
|
|
test['name'],
|
|||
|
|
test['method'],
|
|||
|
|
test['url'],
|
|||
|
|
test['data'],
|
|||
|
|
test['headers']
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if success:
|
|||
|
|
result.passed += 1
|
|||
|
|
print_colored("✓ 通过", Colors.GREEN)
|
|||
|
|
print(f" HTTP状态码: {status_code}")
|
|||
|
|
if isinstance(response_data, dict) and 'code' in response_data:
|
|||
|
|
print(f" 响应码: {response_data.get('code')}")
|
|||
|
|
if 'msg' in response_data:
|
|||
|
|
print(f" 消息: {response_data.get('msg')}")
|
|||
|
|
else:
|
|||
|
|
result.failed += 1
|
|||
|
|
print_colored("✗ 失败", Colors.RED)
|
|||
|
|
print(f" HTTP状态码: {status_code}")
|
|||
|
|
if isinstance(response_data, dict) and 'error' in response_data:
|
|||
|
|
print(f" 错误: {response_data.get('error')}")
|
|||
|
|
|
|||
|
|
result.results.append({
|
|||
|
|
"name": test['name'],
|
|||
|
|
"success": success,
|
|||
|
|
"status_code": status_code,
|
|||
|
|
"response": response_data
|
|||
|
|
})
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
print("-" * 60)
|
|||
|
|
print_colored("2. 登录相关接口测试", Colors.YELLOW)
|
|||
|
|
print("-" * 60)
|
|||
|
|
|
|||
|
|
for test in test_cases[2:4]:
|
|||
|
|
result.total += 1
|
|||
|
|
print(f"测试 {result.total}: {test['name']} ... ", end="", flush=True)
|
|||
|
|
|
|||
|
|
success, status_code, response_data = test_api(
|
|||
|
|
test['name'],
|
|||
|
|
test['method'],
|
|||
|
|
test['url'],
|
|||
|
|
test['data'],
|
|||
|
|
test['headers']
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if success:
|
|||
|
|
result.passed += 1
|
|||
|
|
print_colored("✓ 通过", Colors.GREEN)
|
|||
|
|
print(f" HTTP状态码: {status_code}")
|
|||
|
|
if isinstance(response_data, dict):
|
|||
|
|
if 'code' in response_data:
|
|||
|
|
print(f" 响应码: {response_data.get('code')}")
|
|||
|
|
if 'msg' in response_data:
|
|||
|
|
print(f" 消息: {response_data.get('msg')}")
|
|||
|
|
else:
|
|||
|
|
result.failed += 1
|
|||
|
|
print_colored("✗ 失败", Colors.RED)
|
|||
|
|
print(f" HTTP状态码: {status_code}")
|
|||
|
|
if isinstance(response_data, dict) and 'error' in response_data:
|
|||
|
|
print(f" 错误: {response_data.get('error')}")
|
|||
|
|
|
|||
|
|
result.results.append({
|
|||
|
|
"name": test['name'],
|
|||
|
|
"success": success,
|
|||
|
|
"status_code": status_code,
|
|||
|
|
"response": response_data
|
|||
|
|
})
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
print("-" * 60)
|
|||
|
|
print_colored("3. 系统配置接口测试(需要认证)", Colors.YELLOW)
|
|||
|
|
print("-" * 60)
|
|||
|
|
|
|||
|
|
for test in test_cases[4:6]:
|
|||
|
|
result.total += 1
|
|||
|
|
print(f"测试 {result.total}: {test['name']} ... ", end="", flush=True)
|
|||
|
|
|
|||
|
|
success, status_code, response_data = test_api(
|
|||
|
|
test['name'],
|
|||
|
|
test['method'],
|
|||
|
|
test['url'],
|
|||
|
|
test['data'],
|
|||
|
|
test['headers']
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if success:
|
|||
|
|
result.passed += 1
|
|||
|
|
print_colored("✓ 通过", Colors.GREEN)
|
|||
|
|
print(f" HTTP状态码: {status_code}")
|
|||
|
|
if status_code == 401 or status_code == 403:
|
|||
|
|
print_colored(" (接口存在,但需要有效Token)", Colors.YELLOW)
|
|||
|
|
else:
|
|||
|
|
result.failed += 1
|
|||
|
|
print_colored("✗ 失败", Colors.RED)
|
|||
|
|
print(f" HTTP状态码: {status_code}")
|
|||
|
|
|
|||
|
|
result.results.append({
|
|||
|
|
"name": test['name'],
|
|||
|
|
"success": success,
|
|||
|
|
"status_code": status_code,
|
|||
|
|
"response": response_data
|
|||
|
|
})
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
print("-" * 60)
|
|||
|
|
print_colored("4. 业务接口测试(需要认证)", Colors.YELLOW)
|
|||
|
|
print("-" * 60)
|
|||
|
|
|
|||
|
|
for test in test_cases[6:]:
|
|||
|
|
result.total += 1
|
|||
|
|
print(f"测试 {result.total}: {test['name']} ... ", end="", flush=True)
|
|||
|
|
|
|||
|
|
success, status_code, response_data = test_api(
|
|||
|
|
test['name'],
|
|||
|
|
test['method'],
|
|||
|
|
test['url'],
|
|||
|
|
test['data'],
|
|||
|
|
test['headers']
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if success:
|
|||
|
|
result.passed += 1
|
|||
|
|
print_colored("✓ 通过", Colors.GREEN)
|
|||
|
|
print(f" HTTP状态码: {status_code}")
|
|||
|
|
if status_code == 401 or status_code == 403:
|
|||
|
|
print_colored(" (接口存在,但需要有效Token)", Colors.YELLOW)
|
|||
|
|
else:
|
|||
|
|
result.failed += 1
|
|||
|
|
print_colored("✗ 失败", Colors.RED)
|
|||
|
|
print(f" HTTP状态码: {status_code}")
|
|||
|
|
|
|||
|
|
result.results.append({
|
|||
|
|
"name": test['name'],
|
|||
|
|
"success": success,
|
|||
|
|
"status_code": status_code,
|
|||
|
|
"response": response_data
|
|||
|
|
})
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
# 输出测试结果统计
|
|||
|
|
print("=" * 60)
|
|||
|
|
print_colored("测试结果统计", Colors.BLUE)
|
|||
|
|
print("=" * 60)
|
|||
|
|
print(f"总测试数: {result.total}")
|
|||
|
|
print_colored(f"通过: {result.passed}", Colors.GREEN)
|
|||
|
|
print_colored(f"失败: {result.failed}", Colors.RED)
|
|||
|
|
if result.total > 0:
|
|||
|
|
pass_rate = (result.passed * 100) // result.total
|
|||
|
|
print(f"通过率: {pass_rate}%")
|
|||
|
|
print()
|
|||
|
|
print(f"结束时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
# 输出详细结果
|
|||
|
|
if result.failed > 0:
|
|||
|
|
print_colored("失败的接口详情:", Colors.YELLOW)
|
|||
|
|
for r in result.results:
|
|||
|
|
if not r['success']:
|
|||
|
|
print(f" - {r['name']}: HTTP {r['status_code']}")
|
|||
|
|
print()
|
|||
|
|
|
|||
|
|
# 判断整体结果
|
|||
|
|
if result.failed == 0:
|
|||
|
|
print_colored("所有接口测试通过!", Colors.GREEN)
|
|||
|
|
return 0
|
|||
|
|
else:
|
|||
|
|
print_colored("部分接口测试失败,请检查服务器状态和网络连接", Colors.YELLOW)
|
|||
|
|
print_colored("提示:401/403状态码表示接口存在但需要有效认证", Colors.YELLOW)
|
|||
|
|
return 1
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
try:
|
|||
|
|
exit_code = run_tests()
|
|||
|
|
sys.exit(exit_code)
|
|||
|
|
except KeyboardInterrupt:
|
|||
|
|
print("\n\n测试被用户中断")
|
|||
|
|
sys.exit(1)
|
|||
|
|
except Exception as e:
|
|||
|
|
print_colored(f"\n测试过程中发生错误: {str(e)}", Colors.RED)
|
|||
|
|
import traceback
|
|||
|
|
traceback.print_exc()
|
|||
|
|
sys.exit(1)
|