719 lines
27 KiB
Python
719 lines
27 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
ljwx-boot 健康系统API自动化测试脚本
|
|
|
|
测试覆盖:
|
|
1. 统一健康数据查询
|
|
2. 健康基线生成和查询
|
|
3. 健康评分计算
|
|
4. 健康画像生成
|
|
5. 健康建议生成
|
|
6. 健康预测功能
|
|
7. 任务管理和监控
|
|
|
|
使用方法:
|
|
python health_api_test.py --base-url http://localhost:8080
|
|
"""
|
|
|
|
import requests
|
|
import json
|
|
import time
|
|
import argparse
|
|
from datetime import datetime, timedelta
|
|
from typing import Dict, Any, List, Optional
|
|
import logging
|
|
import sys
|
|
import os
|
|
from db_config import DatabaseConfig
|
|
|
|
# 配置日志
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format='%(asctime)s - %(levelname)s - %(message)s',
|
|
handlers=[
|
|
logging.FileHandler('health_api_test.log'),
|
|
logging.StreamHandler(sys.stdout)
|
|
]
|
|
)
|
|
|
|
class HealthAPITester:
|
|
def __init__(self, base_url: str, auth_url: str = None):
|
|
self.base_url = base_url.rstrip('/')
|
|
self.auth_url = auth_url or "http://192.168.1.83:3333/proxy-default/auth/user_name"
|
|
self.session = requests.Session()
|
|
self.test_results = []
|
|
self.db_config = None
|
|
self.access_token = None
|
|
self.auth_success = False
|
|
self.test_data = {
|
|
'customers': [],
|
|
'users': [],
|
|
'user_devices': [],
|
|
'departments': []
|
|
}
|
|
|
|
# 设置请求头
|
|
self.session.headers.update({
|
|
'Content-Type': 'application/json',
|
|
'Accept': 'application/json'
|
|
})
|
|
|
|
# 先进行身份认证
|
|
self._authenticate()
|
|
|
|
# 初始化数据库连接
|
|
self._init_database()
|
|
|
|
def _authenticate(self):
|
|
"""进行身份认证获取access token"""
|
|
try:
|
|
logging.info("🔐 开始身份认证...")
|
|
|
|
auth_payload = {
|
|
"userName": "admin",
|
|
"password": "80a3d119ee1501354755dfc3c4638d74c67c801689efbed4f25f06cb4b1cd776"
|
|
}
|
|
|
|
response = requests.post(
|
|
self.auth_url,
|
|
json=auth_payload,
|
|
headers={'Content-Type': 'application/json'},
|
|
timeout=30
|
|
)
|
|
|
|
if response.status_code == 200:
|
|
try:
|
|
auth_data = response.json()
|
|
# 根据实际API响应结构获取token,可能的字段名:token, access_token, accessToken等
|
|
token_fields = ['token', 'access_token', 'accessToken', 'data.token', 'result.token']
|
|
|
|
for field in token_fields:
|
|
if '.' in field:
|
|
# 支持嵌套字段如 data.token
|
|
parts = field.split('.')
|
|
value = auth_data
|
|
try:
|
|
for part in parts:
|
|
value = value[part]
|
|
if value:
|
|
self.access_token = value
|
|
break
|
|
except (KeyError, TypeError):
|
|
continue
|
|
else:
|
|
# 直接字段
|
|
if field in auth_data and auth_data[field]:
|
|
self.access_token = auth_data[field]
|
|
break
|
|
|
|
if self.access_token:
|
|
self.auth_success = True
|
|
# 设置Authorization头部
|
|
self.session.headers.update({
|
|
'Authorization': f'Bearer {self.access_token}'
|
|
})
|
|
logging.info("✅ 身份认证成功,已获取访问令牌")
|
|
logging.info(f"🔑 Token: {self.access_token[:20]}...{self.access_token[-10:] if len(self.access_token) > 30 else self.access_token}")
|
|
else:
|
|
logging.warning("⚠️ 认证响应中未找到token字段")
|
|
logging.warning(f"响应内容: {auth_data}")
|
|
|
|
except json.JSONDecodeError:
|
|
logging.error("❌ 认证响应不是有效的JSON格式")
|
|
logging.error(f"响应内容: {response.text}")
|
|
else:
|
|
logging.error(f"❌ 身份认证失败: HTTP {response.status_code}")
|
|
logging.error(f"响应内容: {response.text}")
|
|
|
|
except Exception as e:
|
|
logging.error(f"❌ 身份认证异常: {str(e)}")
|
|
self.auth_success = False
|
|
|
|
def _init_database(self):
|
|
"""初始化数据库连接并加载测试数据"""
|
|
try:
|
|
# 检查数据库配置文件
|
|
config_file = 'db_config.json'
|
|
if not os.path.exists(config_file):
|
|
logging.warning("⚠️ 数据库配置文件不存在,将使用默认测试参数")
|
|
return
|
|
|
|
with open(config_file, 'r') as f:
|
|
db_config = json.load(f)
|
|
|
|
self.db_config = DatabaseConfig(
|
|
host=db_config.get('host', 'localhost'),
|
|
port=db_config.get('port', 3306),
|
|
database=db_config.get('database', 'ljwx'),
|
|
user=db_config.get('user', 'root'),
|
|
password=db_config.get('password', '')
|
|
)
|
|
|
|
if self.db_config.connect():
|
|
logging.info("✅ 数据库连接成功,加载实际测试数据")
|
|
self._load_test_data()
|
|
else:
|
|
logging.warning("⚠️ 数据库连接失败,将使用默认测试参数")
|
|
|
|
except Exception as e:
|
|
logging.warning(f"⚠️ 数据库初始化失败: {e},将使用默认测试参数")
|
|
|
|
def _load_test_data(self):
|
|
"""从数据库加载真实测试数据"""
|
|
try:
|
|
# 加载用户数据
|
|
users = self.db_config.get_users(20)
|
|
self.test_data['users'] = users
|
|
logging.info(f"📊 加载用户数据: {len(users)} 条")
|
|
|
|
# 加载设备数据
|
|
devices = self.db_config.get_devices(20)
|
|
logging.info(f"📊 加载设备数据: {len(devices)} 条")
|
|
|
|
# 加载用户设备关联
|
|
user_devices = self.db_config.get_user_devices(15)
|
|
self.test_data['user_devices'] = user_devices
|
|
logging.info(f"📊 加载用户设备关联: {len(user_devices)} 条")
|
|
|
|
# 获取客户ID(从用户表或系统配置获取)
|
|
if users:
|
|
# 假设所有用户属于同一个客户,使用第一个用户所属的客户ID
|
|
# 这里需要根据实际数据库结构调整
|
|
self.test_data['customers'] = [{'id': 1, 'name': '默认客户'}]
|
|
|
|
# 加载部门数据(如果有)
|
|
try:
|
|
departments = self.db_config.get_departments(10)
|
|
self.test_data['departments'] = departments
|
|
logging.info(f"📊 加载部门数据: {len(departments)} 条")
|
|
except:
|
|
# 如果没有部门表或方法,使用默认值
|
|
self.test_data['departments'] = [{'id': 1, 'name': '默认部门'}]
|
|
|
|
except Exception as e:
|
|
logging.error(f"❌ 加载测试数据失败: {e}")
|
|
|
|
def get_test_customer_id(self) -> int:
|
|
"""获取测试用的客户ID"""
|
|
if self.test_data['customers']:
|
|
return self.test_data['customers'][0]['id']
|
|
return 1 # 默认客户ID
|
|
|
|
def get_test_user_id(self) -> int:
|
|
"""获取测试用的用户ID"""
|
|
if self.test_data['users']:
|
|
return self.test_data['users'][0]['id']
|
|
return 1001 # 默认用户ID
|
|
|
|
def get_test_department_id(self) -> int:
|
|
"""获取测试用的部门ID"""
|
|
if self.test_data['departments']:
|
|
return self.test_data['departments'][0]['id']
|
|
return 1 # 默认部门ID
|
|
|
|
def get_test_device_sn(self) -> str:
|
|
"""获取测试用的设备序列号"""
|
|
if self.test_data['user_devices']:
|
|
return self.test_data['user_devices'][0]['device_sn']
|
|
return 'TEST_DEVICE_001' # 默认设备序列号
|
|
|
|
def log_test_result(self, test_name: str, success: bool, message: str = "", response_time: float = 0):
|
|
"""记录测试结果"""
|
|
result = {
|
|
'test_name': test_name,
|
|
'success': success,
|
|
'message': message,
|
|
'response_time': response_time,
|
|
'timestamp': datetime.now().isoformat()
|
|
}
|
|
self.test_results.append(result)
|
|
|
|
status = "✅ PASS" if success else "❌ FAIL"
|
|
logging.info(f"{status} {test_name} - {message} ({response_time:.2f}ms)")
|
|
|
|
def make_request(self, method: str, url: str, **kwargs) -> Dict[str, Any]:
|
|
"""发送HTTP请求并记录响应时间"""
|
|
start_time = time.time()
|
|
try:
|
|
response = self.session.request(method, url, **kwargs)
|
|
response_time = (time.time() - start_time) * 1000
|
|
|
|
response.raise_for_status()
|
|
return {
|
|
'status_code': response.status_code,
|
|
'data': response.json() if response.content else {},
|
|
'response_time': response_time,
|
|
'success': True
|
|
}
|
|
except requests.RequestException as e:
|
|
response_time = (time.time() - start_time) * 1000
|
|
return {
|
|
'status_code': getattr(e.response, 'status_code', 0) if hasattr(e, 'response') else 0,
|
|
'data': {},
|
|
'response_time': response_time,
|
|
'success': False,
|
|
'error': str(e)
|
|
}
|
|
|
|
def test_unified_health_data_query(self):
|
|
"""测试统一健康数据查询接口"""
|
|
logging.info("🔍 测试统一健康数据查询接口...")
|
|
|
|
customer_id = self.get_test_customer_id()
|
|
user_id = self.get_test_user_id()
|
|
device_sn = self.get_test_device_sn()
|
|
|
|
logging.info(f"📋 使用测试参数: Customer={customer_id}, User={user_id}, Device={device_sn}")
|
|
|
|
# 测试1: POST 统一查询
|
|
query_dto = {
|
|
"customerId": customer_id,
|
|
"userId": user_id,
|
|
"deviceSn": device_sn,
|
|
"startDate": "2025-09-01T00:00:00",
|
|
"endDate": "2025-09-08T23:59:59",
|
|
"page": 1,
|
|
"pageSize": 20,
|
|
"latest": False,
|
|
"queryMode": "all"
|
|
}
|
|
|
|
result = self.make_request(
|
|
'POST',
|
|
f"{self.base_url}/health/unified/query",
|
|
json=query_dto
|
|
)
|
|
|
|
self.log_test_result(
|
|
"统一健康数据查询(POST)",
|
|
result['success'],
|
|
f"返回数据: {result.get('data', {}).get('success', False)}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
# 测试2: GET 简化查询
|
|
params = {
|
|
'customerId': customer_id,
|
|
'userId': user_id,
|
|
'deviceSn': device_sn,
|
|
'startDate': '2025-09-01T00:00:00',
|
|
'endDate': '2025-09-08T23:59:59',
|
|
'page': 1,
|
|
'pageSize': 10,
|
|
'latest': False,
|
|
'queryMode': 'all'
|
|
}
|
|
|
|
result = self.make_request(
|
|
'GET',
|
|
f"{self.base_url}/health/unified/query/simple",
|
|
params=params
|
|
)
|
|
|
|
self.log_test_result(
|
|
"简化健康数据查询(GET)",
|
|
result['success'],
|
|
f"返回数据: {result.get('data', {}).get('success', False)}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
# 测试3: 获取支持的健康指标
|
|
result = self.make_request(
|
|
'GET',
|
|
f"{self.base_url}/health/unified/metrics/supported",
|
|
params={'customerId': customer_id}
|
|
)
|
|
|
|
self.log_test_result(
|
|
"获取支持的健康指标",
|
|
result['success'],
|
|
f"指标数量: {result.get('data', {}).get('total', 0)}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
# 测试4: 获取健康指标配置
|
|
result = self.make_request(
|
|
'GET',
|
|
f"{self.base_url}/health/unified/metrics/config",
|
|
params={'customerId': customer_id}
|
|
)
|
|
|
|
self.log_test_result(
|
|
"获取健康指标配置",
|
|
result['success'],
|
|
f"配置数量: {result.get('data', {}).get('total', 0)}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
# 测试5: 获取表信息
|
|
result = self.make_request(
|
|
'GET',
|
|
f"{self.base_url}/health/unified/table/info",
|
|
params={
|
|
'startDate': '2025-09-01T00:00:00',
|
|
'endDate': '2025-09-08T23:59:59'
|
|
}
|
|
)
|
|
|
|
self.log_test_result(
|
|
"获取健康数据表信息",
|
|
result['success'],
|
|
f"表数量: {result.get('data', {}).get('data', {}).get('tableCount', 0)}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
def test_health_task_management(self):
|
|
"""测试健康任务管理接口"""
|
|
logging.info("⚙️ 测试健康任务管理接口...")
|
|
|
|
# 测试1: 查询任务执行状态
|
|
result = self.make_request(
|
|
'GET',
|
|
f"{self.base_url}/api/health/task/status",
|
|
params={'limit': 10}
|
|
)
|
|
|
|
self.log_test_result(
|
|
"查询任务执行状态",
|
|
result['success'],
|
|
f"日志条数: {len(result.get('data', {}).get('recentLogs', []))}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
# 测试2: 查询健康数据统计
|
|
result = self.make_request(
|
|
'GET',
|
|
f"{self.base_url}/api/health/task/statistics"
|
|
)
|
|
|
|
self.log_test_result(
|
|
"查询健康数据统计",
|
|
result['success'],
|
|
f"基线统计: {len(result.get('data', {}).get('baselineStats', []))}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
# 测试3: 查询分表信息
|
|
result = self.make_request(
|
|
'GET',
|
|
f"{self.base_url}/api/health/task/tables"
|
|
)
|
|
|
|
self.log_test_result(
|
|
"查询分表信息",
|
|
result['success'],
|
|
f"表数量: {result.get('data', {}).get('summary', {}).get('totalTables', 0)}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
# 测试4: 获取缓存统计
|
|
result = self.make_request(
|
|
'GET',
|
|
f"{self.base_url}/api/health/task/cache/statistics"
|
|
)
|
|
|
|
self.log_test_result(
|
|
"获取缓存统计信息",
|
|
result['success'],
|
|
"缓存统计获取成功" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
# 测试5: 获取部门健康概览 (如果有部门ID)
|
|
department_id = 1 # 假设部门ID为1
|
|
result = self.make_request(
|
|
'GET',
|
|
f"{self.base_url}/api/health/task/department/{department_id}/overview",
|
|
params={'date': (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')}
|
|
)
|
|
|
|
self.log_test_result(
|
|
"获取部门健康概览",
|
|
result['success'],
|
|
f"部门ID: {department_id}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
# 测试6: 获取部门健康排名
|
|
result = self.make_request(
|
|
'GET',
|
|
f"{self.base_url}/api/health/task/department/ranking",
|
|
params={
|
|
'feature': 'heart_rate',
|
|
'date': (datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d'),
|
|
'limit': 10
|
|
}
|
|
)
|
|
|
|
self.log_test_result(
|
|
"获取部门健康排名",
|
|
result['success'],
|
|
f"排名数据: {len(result.get('data', {}).get('ranking', []))}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
def test_health_profile(self):
|
|
"""测试健康画像接口"""
|
|
logging.info("👤 测试健康画像接口...")
|
|
|
|
user_id = self.get_test_user_id()
|
|
|
|
# 测试1: 测试接口
|
|
result = self.make_request(
|
|
'GET',
|
|
f"{self.base_url}/health/profile/test"
|
|
)
|
|
|
|
self.log_test_result(
|
|
"健康画像测试接口",
|
|
result['success'],
|
|
"画像系统正常" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
# 测试2: 生成健康基线
|
|
result = self.make_request(
|
|
'POST',
|
|
f"{self.base_url}/health/profile/baseline/generate",
|
|
params={
|
|
'userId': user_id,
|
|
'days': 30
|
|
}
|
|
)
|
|
|
|
self.log_test_result(
|
|
"生成健康基线",
|
|
result['success'],
|
|
f"用户ID: {user_id}, 天数: 30" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
def test_manual_task_execution(self):
|
|
"""测试手动任务执行 (谨慎执行)"""
|
|
logging.info("🔧 测试手动任务执行 (仅读取操作)...")
|
|
|
|
# 注意:这里只测试非破坏性的操作,不执行实际的数据修改任务
|
|
|
|
# 仅测试查询类接口,不执行实际的生成任务
|
|
logging.info("⚠️ 跳过可能影响数据的手动任务执行测试")
|
|
|
|
self.log_test_result(
|
|
"手动任务执行测试",
|
|
True,
|
|
"已跳过潜在风险操作,保护生产数据",
|
|
0
|
|
)
|
|
|
|
def test_cache_operations(self):
|
|
"""测试缓存操作"""
|
|
logging.info("🚀 测试缓存操作...")
|
|
|
|
customer_id = self.get_test_customer_id()
|
|
user_id = self.get_test_user_id()
|
|
|
|
# 测试1: 清除配置缓存
|
|
result = self.make_request(
|
|
'POST',
|
|
f"{self.base_url}/health/unified/cache/clear",
|
|
params={'customerId': customer_id}
|
|
)
|
|
|
|
self.log_test_result(
|
|
"清除健康配置缓存",
|
|
result['success'],
|
|
f"客户ID: {customer_id}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
# 测试2: 清理用户缓存
|
|
result = self.make_request(
|
|
'POST',
|
|
f"{self.base_url}/api/health/task/cache/clear/{user_id}"
|
|
)
|
|
|
|
self.log_test_result(
|
|
"清理用户健康缓存",
|
|
result['success'],
|
|
f"用户ID: {user_id}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
# 测试3: 缓存预热
|
|
result = self.make_request(
|
|
'POST',
|
|
f"{self.base_url}/api/health/task/cache/warmup",
|
|
json=[user_id]
|
|
)
|
|
|
|
self.log_test_result(
|
|
"缓存预热",
|
|
result['success'],
|
|
f"预热用户: {user_id}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
def test_health_metrics_filtering(self):
|
|
"""测试健康指标过滤"""
|
|
logging.info("🔍 测试健康指标过滤...")
|
|
|
|
customer_id = self.get_test_customer_id()
|
|
|
|
# 常见健康指标
|
|
test_metrics = [
|
|
"heart_rate", "blood_oxygen", "temperature",
|
|
"pressure_high", "pressure_low", "stress",
|
|
"step", "calorie", "distance", "sleep"
|
|
]
|
|
|
|
result = self.make_request(
|
|
'GET',
|
|
f"{self.base_url}/health/unified/metrics/filter",
|
|
params={
|
|
'customerId': customer_id,
|
|
'metrics': test_metrics
|
|
}
|
|
)
|
|
|
|
self.log_test_result(
|
|
"健康指标过滤测试",
|
|
result['success'],
|
|
f"原始指标: {len(test_metrics)}, 支持指标: {result.get('data', {}).get('total', 0)}" if result['success'] else result.get('error', ''),
|
|
result['response_time']
|
|
)
|
|
|
|
def run_performance_test(self):
|
|
"""执行性能测试 (自动化模式下跳过)"""
|
|
logging.info("⚡ 性能测试 (自动化模式)...")
|
|
|
|
# 在自动化模式下跳过性能测试以避免对生产系统造成负载
|
|
logging.info("🔒 自动化模式:跳过性能测试,保护生产系统")
|
|
|
|
self.log_test_result(
|
|
"系统性能测试",
|
|
True,
|
|
"自动化模式跳过性能测试,保护生产系统",
|
|
0
|
|
)
|
|
|
|
def run_all_tests(self):
|
|
"""执行所有测试"""
|
|
logging.info(f"🚀 开始执行ljwx-boot健康系统API测试 (Base URL: {self.base_url})")
|
|
|
|
# 检查认证状态
|
|
if not self.auth_success:
|
|
logging.error("❌ 身份认证失败,无法继续测试")
|
|
logging.error("请检查认证URL和登录凭据是否正确")
|
|
return
|
|
|
|
logging.info(f"🔐 认证状态: {'✅ 已认证' if self.auth_success else '❌ 未认证'}")
|
|
|
|
# 显示测试数据摘要
|
|
if self.test_data['users']:
|
|
logging.info(f"📊 测试数据统计:")
|
|
logging.info(f" - 用户数据: {len(self.test_data['users'])} 条")
|
|
logging.info(f" - 设备关联: {len(self.test_data['user_devices'])} 条")
|
|
logging.info(f" - 部门数据: {len(self.test_data['departments'])} 条")
|
|
logging.info(f"📝 使用真实数据: Customer={self.get_test_customer_id()}, User={self.get_test_user_id()}")
|
|
else:
|
|
logging.info("📝 使用默认测试参数 (未连接数据库)")
|
|
|
|
start_time = time.time()
|
|
|
|
# 执行各个测试模块
|
|
try:
|
|
self.test_unified_health_data_query()
|
|
self.test_health_task_management()
|
|
self.test_health_profile()
|
|
self.test_cache_operations()
|
|
self.test_health_metrics_filtering()
|
|
self.test_manual_task_execution()
|
|
self.run_performance_test()
|
|
|
|
except Exception as e:
|
|
logging.error(f"❌ 测试执行过程中出现异常: {str(e)}")
|
|
|
|
# 生成测试报告
|
|
self.generate_test_report(time.time() - start_time)
|
|
|
|
def generate_test_report(self, total_time: float):
|
|
"""生成测试报告"""
|
|
total_tests = len(self.test_results)
|
|
passed_tests = sum(1 for result in self.test_results if result['success'])
|
|
failed_tests = total_tests - passed_tests
|
|
|
|
# 计算平均响应时间
|
|
avg_response_time = sum(result['response_time'] for result in self.test_results) / total_tests if total_tests > 0 else 0
|
|
|
|
logging.info("=" * 80)
|
|
logging.info("📊 ljwx-boot 健康系统API测试报告")
|
|
logging.info("=" * 80)
|
|
logging.info(f"🎯 测试目标: {self.base_url}")
|
|
|
|
# 显示测试数据信息
|
|
if self.test_data['users']:
|
|
logging.info(f"📋 测试数据: 真实数据 (Customer={self.get_test_customer_id()}, User={self.get_test_user_id()})")
|
|
else:
|
|
logging.info(f"📋 测试数据: 默认参数")
|
|
|
|
logging.info(f"🔐 认证状态: {'✅ 已认证' if self.auth_success else '❌ 未认证'}")
|
|
|
|
logging.info(f"📋 总测试数: {total_tests}")
|
|
logging.info(f"✅ 通过测试: {passed_tests}")
|
|
logging.info(f"❌ 失败测试: {failed_tests}")
|
|
logging.info(f"📈 通过率: {(passed_tests / total_tests * 100):.1f}%")
|
|
logging.info(f"⏱️ 总耗时: {total_time:.2f}秒")
|
|
logging.info(f"⚡ 平均响应时间: {avg_response_time:.2f}ms")
|
|
|
|
if failed_tests > 0:
|
|
logging.info("\n❌ 失败的测试:")
|
|
for result in self.test_results:
|
|
if not result['success']:
|
|
logging.info(f" - {result['test_name']}: {result['message']}")
|
|
|
|
logging.info("=" * 80)
|
|
|
|
# 保存详细报告到文件
|
|
report_file = f"health_api_test_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
|
|
with open(report_file, 'w', encoding='utf-8') as f:
|
|
json.dump({
|
|
'summary': {
|
|
'base_url': self.base_url,
|
|
'auth_url': self.auth_url,
|
|
'auth_success': self.auth_success,
|
|
'customer_id': self.get_test_customer_id(),
|
|
'user_id': self.get_test_user_id(),
|
|
'device_sn': self.get_test_device_sn(),
|
|
'department_id': self.get_test_department_id(),
|
|
'data_source': 'real_database' if self.test_data['users'] else 'default_params',
|
|
'total_tests': total_tests,
|
|
'passed_tests': passed_tests,
|
|
'failed_tests': failed_tests,
|
|
'pass_rate': passed_tests / total_tests * 100 if total_tests > 0 else 0,
|
|
'total_time': total_time,
|
|
'avg_response_time': avg_response_time,
|
|
'test_timestamp': datetime.now().isoformat(),
|
|
'test_data_summary': {
|
|
'users_count': len(self.test_data['users']),
|
|
'user_devices_count': len(self.test_data['user_devices']),
|
|
'departments_count': len(self.test_data['departments'])
|
|
}
|
|
},
|
|
'test_results': self.test_results
|
|
}, f, ensure_ascii=False, indent=2)
|
|
|
|
logging.info(f"📄 详细报告已保存到: {report_file}")
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='ljwx-boot 健康系统API自动化测试工具')
|
|
parser.add_argument('--base-url', required=True, help='API服务基础URL (如: http://localhost:8080)')
|
|
parser.add_argument('--auth-url', help='认证API URL (默认: http://192.168.1.83:3333/proxy-default/auth/user_name)')
|
|
|
|
args = parser.parse_args()
|
|
|
|
# 创建测试实例并执行
|
|
# 现在从数据库自动获取实际的客户和用户数据,并自动进行身份认证
|
|
tester = HealthAPITester(args.base_url, args.auth_url)
|
|
tester.run_all_tests()
|
|
|
|
if __name__ == "__main__":
|
|
main() |