#!/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()