| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- #!/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 '<!DOCTYPE html>...'"
- })
- tests.append({
- "name": "TestBaiduAPI::test_baidu_homepage",
- "status": "failed",
- "duration": "1.5s",
- "error": "AssertionError: assert '百度一下' in '<!DOCTYPE html>...'"
- })
- # 保存数据到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()
|