415 lines
13 KiB
Python
Executable File
415 lines
13 KiB
Python
Executable File
#!/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)
|