Files
ai_wht_B/测试认证接口性能.py

502 lines
16 KiB
Python
Raw Permalink Normal View History

2026-01-06 14:18:39 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
测试认证接口性能并生成CSV报告和接口文档
"""
import requests
import time
import csv
from datetime import datetime
# API配置
API_BASE_URL = "http://127.0.0.1:8216"
USERNAME = "13621242430"
PASSWORD = "admin123"
# 测试结果存储
test_results = []
api_docs = []
def test_unified_login():
"""测试统一登录接口(支持手机号和用户名)"""
print("\n" + "-"*80)
print("[1/4] 测试统一登录接口...")
url = f"{API_BASE_URL}/api/auth/login"
# 测试用例1: 使用用户名登录
print(" [1] 使用用户名登录...")
data = {"username": USERNAME, "password": PASSWORD}
try:
start_time = time.time()
response = requests.post(url, json=data, timeout=30)
elapsed_time = (time.time() - start_time) * 1000
success = response.status_code == 200
error = '' if success else response.text
print(f" 状态码: {response.status_code} - 耗时: {elapsed_time:.2f}ms")
test_results.append({
'endpoint': '/api/auth/login (用户名)',
'method': 'POST',
'status_code': response.status_code,
'elapsed_time_ms': f"{elapsed_time:.2f}",
'success': success,
'error': error
})
# 保存token用于后续测试
token = None
if success:
token = response.json().get('data', {}).get('token')
print(f" ✓ 登录成功获取到token")
time.sleep(0.1)
except Exception as e:
print(f" 失败: {str(e)}")
test_results.append({
'endpoint': '/api/auth/login (用户名)',
'method': 'POST',
'status_code': 0,
'elapsed_time_ms': '0',
'success': False,
'error': str(e)
})
token = None
# 测试用例2: 使用手机号登录
print(" [2] 使用手机号登录...")
data = {"phone": USERNAME, "password": PASSWORD}
try:
start_time = time.time()
response = requests.post(url, json=data, timeout=30)
elapsed_time = (time.time() - start_time) * 1000
success = response.status_code == 200
error = '' if success else response.text
print(f" 状态码: {response.status_code} - 耗时: {elapsed_time:.2f}ms")
test_results.append({
'endpoint': '/api/auth/login (手机号)',
'method': 'POST',
'status_code': response.status_code,
'elapsed_time_ms': f"{elapsed_time:.2f}",
'success': success,
'error': error
})
time.sleep(0.1)
except Exception as e:
print(f" 失败: {str(e)}")
test_results.append({
'endpoint': '/api/auth/login (手机号)',
'method': 'POST',
'status_code': 0,
'elapsed_time_ms': '0',
'success': False,
'error': str(e)
})
# 测试用例3: 错误密码
print(" [3] 测试错误密码...")
data = {"username": USERNAME, "password": "wrong_password"}
try:
start_time = time.time()
response = requests.post(url, json=data, timeout=30)
elapsed_time = (time.time() - start_time) * 1000
success = response.status_code == 401 # 期望返回401
error = '' if success else response.text
print(f" 状态码: {response.status_code} - 耗时: {elapsed_time:.2f}ms")
test_results.append({
'endpoint': '/api/auth/login (错误密码)',
'method': 'POST',
'status_code': response.status_code,
'elapsed_time_ms': f"{elapsed_time:.2f}",
'success': success,
'error': error
})
time.sleep(0.1)
except Exception as e:
print(f" 失败: {str(e)}")
test_results.append({
'endpoint': '/api/auth/login (错误密码)',
'method': 'POST',
'status_code': 0,
'elapsed_time_ms': '0',
'success': False,
'error': str(e)
})
# 测试用例4: 缺少参数
print(" [4] 测试缺少参数...")
data = {"username": USERNAME} # 缺少password
try:
start_time = time.time()
response = requests.post(url, json=data, timeout=30)
elapsed_time = (time.time() - start_time) * 1000
success = response.status_code == 400 # 期望返回400
error = '' if success else response.text
print(f" 状态码: {response.status_code} - 耗时: {elapsed_time:.2f}ms")
test_results.append({
'endpoint': '/api/auth/login (缺少参数)',
'method': 'POST',
'status_code': response.status_code,
'elapsed_time_ms': f"{elapsed_time:.2f}",
'success': success,
'error': error
})
except Exception as e:
print(f" 失败: {str(e)}")
test_results.append({
'endpoint': '/api/auth/login (缺少参数)',
'method': 'POST',
'status_code': 0,
'elapsed_time_ms': '0',
'success': False,
'error': str(e)
})
# 添加接口文档
api_docs.append({
'endpoint': '/api/auth/login',
'method': 'POST',
'description': '统一登录接口(支持企业主和员工,支持手机号或用户名登录)',
'auth': '无需认证',
'params': 'username/phone (二选一), password',
'response': '返回token和用户信息含企业信息'
})
return token
def test_employee_login():
"""测试员工登录接口"""
print("\n" + "-"*80)
print("[2/4] 测试员工登录接口...")
url = f"{API_BASE_URL}/api/auth/employee/login"
# 测试用例1: 正常登录
print(" [1] 员工正常登录...")
data = {"phone": USERNAME, "password": PASSWORD}
try:
start_time = time.time()
response = requests.post(url, json=data, timeout=30)
elapsed_time = (time.time() - start_time) * 1000
success = response.status_code == 200
error = '' if success else response.text
print(f" 状态码: {response.status_code} - 耗时: {elapsed_time:.2f}ms")
test_results.append({
'endpoint': '/api/auth/employee/login',
'method': 'POST',
'status_code': response.status_code,
'elapsed_time_ms': f"{elapsed_time:.2f}",
'success': success,
'error': error
})
time.sleep(0.1)
except Exception as e:
print(f" 失败: {str(e)}")
test_results.append({
'endpoint': '/api/auth/employee/login',
'method': 'POST',
'status_code': 0,
'elapsed_time_ms': '0',
'success': False,
'error': str(e)
})
# 测试用例2: 错误密码
print(" [2] 员工错误密码...")
data = {"phone": USERNAME, "password": "wrong_password"}
try:
start_time = time.time()
response = requests.post(url, json=data, timeout=30)
elapsed_time = (time.time() - start_time) * 1000
success = response.status_code == 401
error = '' if success else response.text
print(f" 状态码: {response.status_code} - 耗时: {elapsed_time:.2f}ms")
test_results.append({
'endpoint': '/api/auth/employee/login (错误密码)',
'method': 'POST',
'status_code': response.status_code,
'elapsed_time_ms': f"{elapsed_time:.2f}",
'success': success,
'error': error
})
except Exception as e:
print(f" 失败: {str(e)}")
test_results.append({
'endpoint': '/api/auth/employee/login (错误密码)',
'method': 'POST',
'status_code': 0,
'elapsed_time_ms': '0',
'success': False,
'error': str(e)
})
# 添加接口文档
api_docs.append({
'endpoint': '/api/auth/employee/login',
'method': 'POST',
'description': '员工登录接口(仅支持手机号登录)',
'auth': '无需认证',
'params': 'phone, password',
'response': '返回token和员工信息含企业信息、小红书绑定状态'
})
def test_logout(token):
"""测试用户登出接口"""
print("\n" + "-"*80)
print("[3/4] 测试用户登出接口...")
url = f"{API_BASE_URL}/api/auth/logout"
# 测试用例1: 带token登出
if token:
print(" [1] 带token登出...")
headers = {"Authorization": f"Bearer {token}"}
try:
start_time = time.time()
response = requests.post(url, headers=headers, timeout=30)
elapsed_time = (time.time() - start_time) * 1000
success = response.status_code == 200
error = '' if success else response.text
print(f" 状态码: {response.status_code} - 耗时: {elapsed_time:.2f}ms")
test_results.append({
'endpoint': '/api/auth/logout (带token)',
'method': 'POST',
'status_code': response.status_code,
'elapsed_time_ms': f"{elapsed_time:.2f}",
'success': success,
'error': error
})
time.sleep(0.1)
except Exception as e:
print(f" 失败: {str(e)}")
test_results.append({
'endpoint': '/api/auth/logout (带token)',
'method': 'POST',
'status_code': 0,
'elapsed_time_ms': '0',
'success': False,
'error': str(e)
})
# 测试用例2: 不带token登出
print(" [2] 不带token登出...")
try:
start_time = time.time()
response = requests.post(url, timeout=30)
elapsed_time = (time.time() - start_time) * 1000
success = response.status_code == 200
error = '' if success else response.text
print(f" 状态码: {response.status_code} - 耗时: {elapsed_time:.2f}ms")
test_results.append({
'endpoint': '/api/auth/logout (不带token)',
'method': 'POST',
'status_code': response.status_code,
'elapsed_time_ms': f"{elapsed_time:.2f}",
'success': success,
'error': error
})
except Exception as e:
print(f" 失败: {str(e)}")
test_results.append({
'endpoint': '/api/auth/logout (不带token)',
'method': 'POST',
'status_code': 0,
'elapsed_time_ms': '0',
'success': False,
'error': str(e)
})
# 添加接口文档
api_docs.append({
'endpoint': '/api/auth/logout',
'method': 'POST',
'description': '用户登出接口',
'auth': '可选建议带token',
'params': '',
'response': '返回登出成功消息'
})
def test_concurrent_login():
"""测试并发登录性能"""
print("\n" + "-"*80)
print("[4/4] 测试并发登录性能...")
url = f"{API_BASE_URL}/api/auth/login"
data = {"username": USERNAME, "password": PASSWORD}
concurrent_count = 5
print(f" 同时发起{concurrent_count}个登录请求...")
import concurrent.futures
def single_login():
start_time = time.time()
response = requests.post(url, json=data, timeout=30)
elapsed_time = (time.time() - start_time) * 1000
return response.status_code, elapsed_time
try:
with concurrent.futures.ThreadPoolExecutor(max_workers=concurrent_count) as executor:
overall_start = time.time()
futures = [executor.submit(single_login) for _ in range(concurrent_count)]
results = [f.result() for f in concurrent.futures.as_completed(futures)]
overall_time = (time.time() - overall_start) * 1000
success_count = sum(1 for status, _ in results if status == 200)
avg_time = sum(t for _, t in results) / len(results)
print(f" 总耗时: {overall_time:.2f}ms")
print(f" 成功数: {success_count}/{concurrent_count}")
print(f" 平均单次耗时: {avg_time:.2f}ms")
test_results.append({
'endpoint': f'/api/auth/login (并发{concurrent_count}个)',
'method': 'POST',
'status_code': 200 if success_count == concurrent_count else 'mixed',
'elapsed_time_ms': f"{avg_time:.2f}",
'success': success_count == concurrent_count,
'error': f'成功{success_count}/{concurrent_count}, 总耗时{overall_time:.2f}ms'
})
except Exception as e:
print(f" 失败: {str(e)}")
test_results.append({
'endpoint': f'/api/auth/login (并发{concurrent_count}个)',
'method': 'POST',
'status_code': 0,
'elapsed_time_ms': '0',
'success': False,
'error': str(e)
})
def save_to_csv():
"""保存测试结果到CSV文件"""
timestamp = datetime.now().strftime('%Y%m%d')
filename = f'认证接口性能测试_{timestamp}.csv'
with open(filename, 'w', newline='', encoding='utf-8-sig') as f:
writer = csv.DictWriter(f, fieldnames=[
'endpoint', 'method', 'status_code', 'elapsed_time_ms', 'success', 'error'
])
writer.writeheader()
writer.writerows(test_results)
print(f"\n✓ 性能测试结果已保存到: {filename}")
return filename
def save_api_docs():
"""保存接口文档到CSV文件"""
timestamp = datetime.now().strftime('%Y%m%d')
filename = f'认证接口文档_{timestamp}.csv'
with open(filename, 'w', newline='', encoding='utf-8-sig') as f:
writer = csv.DictWriter(f, fieldnames=[
'endpoint', 'method', 'description', 'auth', 'params', 'response'
])
writer.writeheader()
writer.writerows(api_docs)
print(f"✓ 接口文档已保存到: {filename}")
return filename
def print_summary():
"""打印测试摘要"""
print("\n" + "="*80)
print("测试摘要")
print("="*80)
total = len(test_results)
success = sum(1 for r in test_results if r['success'])
failed = total - success
times = [float(r['elapsed_time_ms']) for r in test_results if r['elapsed_time_ms'] != '0']
avg_time = sum(times) / len(times) if times else 0
max_time = max(times) if times else 0
min_time = min(times) if times else 0
print(f"总测试数: {total}")
print(f"成功: {success} ({success/total*100:.1f}%)")
print(f"失败: {failed} ({failed/total*100:.1f}%)")
print(f"平均耗时: {avg_time:.2f}ms")
print(f"最大耗时: {max_time:.2f}ms")
print(f"最小耗时: {min_time:.2f}ms")
print("="*80)
def main():
"""主函数"""
print("="*80)
print("认证接口性能测试工具")
print(f"测试时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print(f"API地址: {API_BASE_URL}")
print("="*80)
# 执行所有测试
token = test_unified_login()
test_employee_login()
test_logout(token)
test_concurrent_login()
# 打印摘要
print_summary()
# 保存结果
csv_file = save_to_csv()
doc_file = save_api_docs()
print(f"\n✓ 测试完成!")
print(f" - 性能数据: {csv_file}")
print(f" - 接口文档: {doc_file}")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\n\n✗ 测试被用户中断")
except Exception as e:
print(f"\n✗ 测试异常: {e}")
import traceback
traceback.print_exc()