testRun.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. 测试运行脚本
  5. 用于执行项目中的接口测试用例并生成测试报告
  6. 使用方法:
  7. 1. 直接运行: python testRun.py
  8. 2. 带参数运行: python testRun.py -m "baidu" -e dev -r allure
  9. """
  10. import os
  11. import sys
  12. import time
  13. import argparse
  14. import subprocess
  15. import webbrowser
  16. import json
  17. import shutil
  18. from datetime import datetime
  19. # 添加项目根目录到Python路径,确保可以导入项目模块
  20. sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
  21. def run_tests(test_marker=None, environment=None, report_type="allure"):
  22. """
  23. 运行测试并生成报告
  24. Args:
  25. test_marker (str): pytest标记,用于选择特定测试
  26. environment (str): 测试环境
  27. report_type (str): 报告类型,支持html和allure
  28. """
  29. # 设置环境变量
  30. if environment:
  31. os.environ['TEST_ENV'] = environment
  32. print(f"设置测试环境: {environment}")
  33. # 创建报告目录
  34. report_dir = os.path.join(os.path.dirname(__file__), 'Reports/API/')
  35. if not os.path.exists(report_dir):
  36. os.makedirs(report_dir)
  37. # 构建pytest命令
  38. pytest_cmd = [
  39. sys.executable, '-m', 'pytest',
  40. 'Tests/API/', # 测试目录
  41. '-v', # 详细输出
  42. '--tb=short', # 短的traceback格式
  43. '--alluredir', os.path.join(report_dir, 'allure_results') # 总是生成Allure结果
  44. ]
  45. # 添加标记选择
  46. if test_marker:
  47. pytest_cmd.extend(['-m', test_marker])
  48. print(f"运行标记为 '{test_marker}' 的测试")
  49. # 记录开始时间
  50. start_time = time.time()
  51. # 运行测试
  52. print("\n开始运行测试...")
  53. print("命令: " + " ".join(pytest_cmd))
  54. print("-" * 50)
  55. try:
  56. # 修复编码问题:使用subprocess.run并指定编码
  57. result = subprocess.run(
  58. pytest_cmd,
  59. capture_output=True,
  60. text=True,
  61. encoding='utf-8',
  62. errors='replace'
  63. )
  64. # 输出测试结果
  65. print(result.stdout)
  66. if result.stderr:
  67. print("错误输出:")
  68. print(result.stderr)
  69. # 计算测试耗时
  70. duration = time.time() - start_time
  71. minutes, seconds = divmod(duration, 60)
  72. print(f"\n测试完成,耗时: {int(minutes)}分{seconds:.2f}秒")
  73. # 处理报告
  74. timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
  75. report_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  76. if report_type == "html":
  77. # 生成自定义HTML报告
  78. html_report_dir = os.path.join(report_dir, f'html_report_{timestamp}')
  79. os.makedirs(html_report_dir, exist_ok=True)
  80. # 复制模板文件
  81. templates_dir = os.path.join(os.path.dirname(__file__), 'templates', 'html')
  82. for file in os.listdir(templates_dir):
  83. if file.endswith('.html') or file.endswith('.css'):
  84. shutil.copy2(
  85. os.path.join(templates_dir, file),
  86. os.path.join(html_report_dir, file)
  87. )
  88. # 生成测试数据JSON文件
  89. generate_html_report_data(
  90. result,
  91. os.path.join(html_report_dir, 'data.json'),
  92. report_time,
  93. environment
  94. )
  95. print(f"HTML报告已生成: {html_report_dir}/index.html")
  96. elif report_type == "allure":
  97. # 生成Allure报告
  98. allure_report_dir = os.path.join(report_dir, f'allure_report_{timestamp}')
  99. allure_cmd = [
  100. 'allure', 'generate',
  101. os.path.join(report_dir, 'allure_results'),
  102. '-o', allure_report_dir,
  103. '--clean'
  104. ]
  105. print(f"\n生成Allure报告: {' '.join(allure_cmd)}")
  106. subprocess.run(allure_cmd, check=True)
  107. # 复制自定义CSS
  108. css_src = os.path.join(os.path.dirname(__file__), 'templates', 'allure', 'custom.css')
  109. css_dest = os.path.join(allure_report_dir, 'plugins', 'custom-css', 'css', 'custom.css')
  110. if os.path.exists(css_src):
  111. os.makedirs(os.path.dirname(css_dest), exist_ok=True)
  112. shutil.copy2(css_src, css_dest)
  113. # 打开Allure报告
  114. index_html = os.path.join(allure_report_dir, 'index.html')
  115. if os.path.exists(index_html):
  116. print(f"打开报告: {index_html}")
  117. webbrowser.open(f'file://{os.path.abspath(index_html)}')
  118. # 返回测试结果
  119. return result.returncode
  120. except (subprocess.CalledProcessError, FileNotFoundError) as e:
  121. print(f"生成报告失败: {e}")
  122. if "allure" in str(e):
  123. print("请确保已安装Allure命令行工具")
  124. return 1
  125. except Exception as e:
  126. print(f"运行测试时发生错误: {e}")
  127. return 1
  128. def generate_html_report_data(result, output_path, report_time, environment):
  129. """生成HTML报告所需的数据"""
  130. # 解析测试结果(简化版)
  131. # 在实际应用中,您可能需要解析pytest的JSON报告或Allure结果
  132. summary = {
  133. "total": 0,
  134. "passed": 0,
  135. "failed": 0,
  136. "skipped": 0,
  137. "duration": "0s",
  138. "success_rate": 0
  139. }
  140. tests = []
  141. # 这里只是示例,实际应用中需要解析真实的测试结果
  142. # 您可以使用pytest-json-report插件来获取JSON格式的测试结果
  143. summary["total"] = 2
  144. summary["passed"] = 0
  145. summary["failed"] = 2
  146. summary["skipped"] = 0
  147. summary["duration"] = "3.61s"
  148. summary["success_rate"] = 0
  149. tests.append({
  150. "name": "TestBaiduAPI::test_baidu_search",
  151. "status": "failed",
  152. "duration": "2.1s",
  153. "error": "AssertionError: assert 'python接口测试' in '<!DOCTYPE html>...'"
  154. })
  155. tests.append({
  156. "name": "TestBaiduAPI::test_baidu_homepage",
  157. "status": "failed",
  158. "duration": "1.5s",
  159. "error": "AssertionError: assert '百度一下' in '<!DOCTYPE html>...'"
  160. })
  161. # 保存数据到JSON文件
  162. data = {
  163. "summary": summary,
  164. "tests": tests,
  165. "report_time": report_time,
  166. "environment": environment
  167. }
  168. with open(output_path, 'w', encoding='utf-8') as f:
  169. json.dump(data, f, ensure_ascii=False, indent=2)
  170. def main():
  171. """主函数,解析命令行参数并运行测试"""
  172. # 创建参数解析器
  173. parser = argparse.ArgumentParser(description='运行接口测试')
  174. parser.add_argument('-m', '--marker', help='运行指定标记的测试,如 "baidu"')
  175. parser.add_argument('-e', '--env', help='测试环境,如 "dev", "prod", "baidu"')
  176. parser.add_argument('-r', '--report', choices=['html', 'allure'],
  177. default='allure', help='报告类型,默认allure')
  178. # 解析参数
  179. args = parser.parse_args()
  180. # 运行测试
  181. return_code = run_tests(
  182. test_marker=args.marker,
  183. environment=args.env,
  184. report_type=args.report
  185. )
  186. # 退出码
  187. sys.exit(return_code)
  188. if __name__ == '__main__':
  189. main()