2026-1-6
This commit is contained in:
501
测试认证接口性能.py
Normal file
501
测试认证接口性能.py
Normal file
@@ -0,0 +1,501 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user