一、前言
在持续集成和自动化测试中,测试报告的管理是一个重要环节。Allure作为一款优秀的测试报告框架,能够生成美观且详细的测试报告。本文将介绍如何使用Python脚本实现Allure测试报告的历史备份与清理功能,帮助团队更好地管理测试报告。
- 安装依赖库:pip install allure-pytest shutil which pytest pathlib
二、核心功能解析
2.1、 报告目录结构管理
# 获取项目根路径
project_path = Path(__file__).parent.parent
reports_path = project_path / "reports"
# 定义源目录和目标基础目录
source_dirs = ["allure-report", "allure-results"]
history_base = reports_path / "History"
timestamp = time.strftime('%Y%m%d%H%M%S', time.localtime())
target_dir = history_base / timestamp
这段代码建立了清晰的目录结构:
- Path(file).parent:代码当前所在路径
- reports/allure-report:生成的HTML报告
- reports/allure-results:原始测试结果
- reports/History:历史备份目录,按时间戳分类
2.2、 跨平台备份实现
if operating_system == "Windows":
# Windows系统使用robocopy
subprocess.run(
["robocopy", str(source), str(target_dir / source_dir), "/E", "/NJH", "/NJS"],
shell=True,
check=True
)
else:
# 非Windows系统使用shutil
shutil.copytree(
src=source,
dst=target_dir / source_dir,
dirs_exist_ok=True # Python 3.8+ 支持
)
代码实现了跨平台兼容:
- Windows使用robocopy命令,效率高且支持增量复制
- Linux/Mac使用Python标准库shutil,兼容性好
- 处理了不同系统的路径差异问题
2.3、历史数据保留机制
current_dir = Path(__file__).parent.absolute()
history_backup = current_dir / "reports" / "history_backup"
# 保留历史数据(如果存在)
if os.path.exists(f"{results_dir}/history"):
shutil.copytree(f"{results_dir}/history", history_backup)
# 清空结果目录
shutil.rmtree(report_dir, ignore_errors=True)
shutil.rmtree(results_dir, ignore_errors=True)
os.makedirs(results_dir, exist_ok=True)
# 恢复历史数据
if os.path.exists(history_backup):
shutil.copytree(history_backup, f"{results_dir}/history")
shutil.rmtree(history_backup)
#这里是要放升成报告数据和生成报告的代码
#拷贝趋势图支撑数据
if operating_system == "Windows":
os.system(f'xcopy /E /I /Y "{report_dir}/history" "{results_dir}/history"')
else:
os.system(f"cp -r {report_dir}/history {results_dir}/history")
os.system(f'allure generate --clean --history-trend {results_dir} -o {report_dir}')
这一机制确保了:
- 保留历史数据和备份代码是两回事
- 历史数据是为了显示趋势图
- 在执行新测试前备份历史数据
- 清理旧报告目录
- 恢复历史数据到新生成的报告中
三、关键技术点
3.1、 路径处理最佳实践
from pathlib import Path
current_dir = Path(__file__).parent.absolute()
results_dir = current_dir / "reports" / "allure-results"
优点:
- 自动处理不同操作系统的路径分隔符
- 提供丰富的路径操作方法
- 代码可读性更高
3.2、子进程调用安全处理
try:
subprocess.run(..., check=True)
except subprocess.CalledProcessError as e:
if e.returncode <= 1: # robocopy返回码1是正常情况
print(f"{source_dir} 备份完成(返回码: {e.returncode})")
else:
raise RuntimeError(...) from e
关键点:
- 使用check=True自动检查命令执行状态
- 处理特定工具的返回码(如robocopy返回1表示成功但有文件未复制)
- 异常链式抛出保持完整堆栈信息
3.3、 环境信息记录
import json
import sys
import socket
from pathlib import Path
#获取文档所在路径
BASE_DIR = Path(__file__).parent.parent
sys.path.append(str(BASE_DIR))
executor_info = {
"name": socket.gethostname(),
"buildName": socket.gethostbyname(socket.gethostname())
}
def runexecutors():
with open(f"{BASE_DIR}/reports/allure-results/executor.json", "w") as f:
json.dump(executor_info, f)
if __name__ == '__main__':
runexecutors()
print(f"文件已写入:{BASE_DIR}/reports/allure-results/executor.json")
with open(f"{BASE_DIR}/reports/allure-results/executor.json", "r") as f:
print("文件内容:", json.load(f))
env = [os.system(f'echo {x} >> {results_dir}/environment.properties') for x in [f"MJCONFIG={os.getenv('MJCONFIG')}",f"MJACCOUNT={os.getenv('MJACCOUNT')}"]]
executors = runexecutors() #调用上面的runexecutors方法
将环境变量写入Allure报告,便于后续分析:
- 记录测试运行时的关键配置
- 方便复现问题
- 支持多环境测试结果对比
四、完整工作流程
4.1、准备阶段
# 获取当前文件的绝对路径
operating_system = platform.system()
current_dir = Path(__file__).parent.absolute()
# 使用绝对路径定义报告目录
results_dir = current_dir / "reports" / "allure-results"
report_dir = current_dir / "reports" / "allure-report"
history_backup = current_dir / "reports" / "history_backup"
4.2、备份历史数据并清空报告
# 保留历史数据(如果存在)
if os.path.exists(f"{results_dir}/history"):
shutil.copytree(f"{results_dir}/history", history_backup)
# 清空结果目录
shutil.rmtree(report_dir, ignore_errors=True)
shutil.rmtree(results_dir, ignore_errors=True)
os.makedirs(results_dir, exist_ok=True)
# 恢复历史数据
if os.path.exists(history_backup):
shutil.copytree(history_backup, f"{results_dir}/history")
shutil.rmtree(history_backup)
4.3、测试执行
cmd = ['pytest',str(Path(__file__).absolute()), f'--alluredir={results_dir}', '-v']
subprocess.run(cmd, check=False)
4.4、拷贝趋势图支撑数据
#拷贝趋势图支撑数据
if operating_system == "Windows":
os.system(f'xcopy /E /I /Y "{report_dir}/history" "{results_dir}/history"')
else:
os.system(f"cp -r {report_dir}/history {results_dir}/history")
4.5、报告生成
os.system(f'allure generate --clean --history-trend {results_dir} -o {report_dir}')
4.6、历史备份
#!/usr/bin/python
# -*- coding: utf-8 -*-
import shutil
import subprocess
import time
from pathlib import Path
import platform
from tools.appversion_report import safe_write_appversion
#备份测试报告
def backup_allure_reports(operating_system):
"""
:backup_allure_reports: 备份测试报告
:param operating_system: platform.system()方法返回的值
:return: 无返回
"""
# 获取项目根路径
project_path = Path(__file__).parent.parent
reports_path = project_path / "reports"
# 定义源目录和目标基础目录
source_dirs = ["allure-report", "allure-results"]
history_base = reports_path / "History"
timestamp = time.strftime('%Y%m%d%H%M%S', time.localtime())
target_dir = history_base / timestamp
safe_write_appversion(timestamp)
# 确保目标目录存在
target_dir.mkdir(parents=True, exist_ok=True)
print(f"备份目录: {target_dir}")
if operating_system == "Windows":
# Windows系统使用robocopy
for source_dir in source_dirs:
source = reports_path / source_dir
if source.exists():
try:
subprocess.run(
["robocopy", str(source), str(target_dir / source_dir), "/E", "/NJH", "/NJS"],
shell=True,
check=True
)
print(f"成功备份 {source_dir} 到 {target_dir}")
except subprocess.CalledProcessError as e:
if e.returncode <= 1: # robocopy返回码1是正常情况
print(f"{source_dir} 备份完成(返回码: {e.returncode})")
else:
raise RuntimeError(f"robocopy备份 {source_dir} 失败,错误码: {e.returncode}") from e
else:
print(f"警告: 源目录 {source_dir} 不存在")
else:
# 非Windows系统使用shutil
for source_dir in source_dirs:
source = reports_path / source_dir
if source.exists():
try:
shutil.copytree(
src=source,
dst=target_dir / source_dir,
dirs_exist_ok=True # Python 3.8+ 支持
)
print(f"成功备份 {source_dir} 到 {target_dir}")
except Exception as e:
print(f"备份 {source_dir} 失败: {e}")
else:
print(f"警告: 源目录 {source_dir} 不存在")
print("备份操作完成")
if __name__ == "__main__":
operating_system = platform.system()
backup_allure_reports(operating_system)
- 按时间戳创建备份目录
- 跨平台复制报告数据
- 记录备份版本信息
4.7、报告服务
os.system(f'python -m http.server 8000 --directory {report_dir}')