#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 测试运行脚本 用于执行项目中的接口测试用例并生成测试报告 使用方法: 1. 直接运行: python testRun.py 2. 带参数运行: python testRun.py -m "baidu" -e dev -r allure """ import os import sys import time import argparse import subprocess import webbrowser import json import shutil from datetime import datetime # 添加项目根目录到Python路径,确保可以导入项目模块 sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) def run_tests(test_marker=None, environment=None, report_type="allure"): """ 运行测试并生成报告 Args: test_marker (str): pytest标记,用于选择特定测试 environment (str): 测试环境 report_type (str): 报告类型,支持html和allure """ # 设置环境变量 if environment: os.environ['TEST_ENV'] = environment print(f"设置测试环境: {environment}") # 创建报告目录 report_dir = os.path.join(os.path.dirname(__file__), 'Reports/API/') if not os.path.exists(report_dir): os.makedirs(report_dir) # 构建pytest命令 pytest_cmd = [ sys.executable, '-m', 'pytest', 'Tests/API/', # 测试目录 '-v', # 详细输出 '--tb=short', # 短的traceback格式 '--alluredir', os.path.join(report_dir, 'allure_results') # 总是生成Allure结果 ] # 添加标记选择 if test_marker: pytest_cmd.extend(['-m', test_marker]) print(f"运行标记为 '{test_marker}' 的测试") # 记录开始时间 start_time = time.time() # 运行测试 print("\n开始运行测试...") print("命令: " + " ".join(pytest_cmd)) print("-" * 50) try: # 修复编码问题:使用subprocess.run并指定编码 result = subprocess.run( pytest_cmd, capture_output=True, text=True, encoding='utf-8', errors='replace' ) # 输出测试结果 print(result.stdout) if result.stderr: print("错误输出:") print(result.stderr) # 计算测试耗时 duration = time.time() - start_time minutes, seconds = divmod(duration, 60) print(f"\n测试完成,耗时: {int(minutes)}分{seconds:.2f}秒") # 处理报告 timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") report_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") if report_type == "html": # 生成自定义HTML报告 html_report_dir = os.path.join(report_dir, f'html_report_{timestamp}') os.makedirs(html_report_dir, exist_ok=True) # 复制模板文件 templates_dir = os.path.join(os.path.dirname(__file__), 'templates', 'html') for file in os.listdir(templates_dir): if file.endswith('.html') or file.endswith('.css'): shutil.copy2( os.path.join(templates_dir, file), os.path.join(html_report_dir, file) ) # 生成测试数据JSON文件 generate_html_report_data( result, os.path.join(html_report_dir, 'data.json'), report_time, environment ) print(f"HTML报告已生成: {html_report_dir}/index.html") elif report_type == "allure": # 生成Allure报告 allure_report_dir = os.path.join(report_dir, f'allure_report_{timestamp}') allure_cmd = [ 'allure', 'generate', os.path.join(report_dir, 'allure_results'), '-o', allure_report_dir, '--clean' ] print(f"\n生成Allure报告: {' '.join(allure_cmd)}") subprocess.run(allure_cmd, check=True) # 复制自定义CSS css_src = os.path.join(os.path.dirname(__file__), 'templates', 'allure', 'custom.css') css_dest = os.path.join(allure_report_dir, 'plugins', 'custom-css', 'css', 'custom.css') if os.path.exists(css_src): os.makedirs(os.path.dirname(css_dest), exist_ok=True) shutil.copy2(css_src, css_dest) # 打开Allure报告 index_html = os.path.join(allure_report_dir, 'index.html') if os.path.exists(index_html): print(f"打开报告: {index_html}") webbrowser.open(f'file://{os.path.abspath(index_html)}') # 返回测试结果 return result.returncode except (subprocess.CalledProcessError, FileNotFoundError) as e: print(f"生成报告失败: {e}") if "allure" in str(e): print("请确保已安装Allure命令行工具") return 1 except Exception as e: print(f"运行测试时发生错误: {e}") return 1 def generate_html_report_data(result, output_path, report_time, environment): """生成HTML报告所需的数据""" # 解析测试结果(简化版) # 在实际应用中,您可能需要解析pytest的JSON报告或Allure结果 summary = { "total": 0, "passed": 0, "failed": 0, "skipped": 0, "duration": "0s", "success_rate": 0 } tests = [] # 这里只是示例,实际应用中需要解析真实的测试结果 # 您可以使用pytest-json-report插件来获取JSON格式的测试结果 summary["total"] = 2 summary["passed"] = 0 summary["failed"] = 2 summary["skipped"] = 0 summary["duration"] = "3.61s" summary["success_rate"] = 0 tests.append({ "name": "TestBaiduAPI::test_baidu_search", "status": "failed", "duration": "2.1s", "error": "AssertionError: assert 'python接口测试' in '...'" }) tests.append({ "name": "TestBaiduAPI::test_baidu_homepage", "status": "failed", "duration": "1.5s", "error": "AssertionError: assert '百度一下' in '...'" }) # 保存数据到JSON文件 data = { "summary": summary, "tests": tests, "report_time": report_time, "environment": environment } with open(output_path, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) def main(): """主函数,解析命令行参数并运行测试""" # 创建参数解析器 parser = argparse.ArgumentParser(description='运行接口测试') parser.add_argument('-m', '--marker', help='运行指定标记的测试,如 "baidu"') parser.add_argument('-e', '--env', help='测试环境,如 "dev", "prod", "baidu"') parser.add_argument('-r', '--report', choices=['html', 'allure'], default='allure', help='报告类型,默认allure') # 解析参数 args = parser.parse_args() # 运行测试 return_code = run_tests( test_marker=args.marker, environment=args.env, report_type=args.report ) # 退出码 sys.exit(return_code) if __name__ == '__main__': main()