Allure测试报告管理

一、前言

        在持续集成和自动化测试中,测试报告的管理是一个重要环节。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}')
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容