Skip to main content

pytest-pure-report

美观、实用的 pytest HTML 报告插件,提供清晰的测试统计和丰富的交互功能。

功能特性

统计与可视化

  • 完整的测试状态统计:通过、失败、错误、跳过、预期失败、意外通过、未执行
  • 饼图直观展示通过率,堆叠条形图展示各测试类的用例分布
  • 智能统计公式:总用例数、已收集、有效用例数、通过率

自定义与设计

  • 自定义 Logo(支持本地图片或远程 URL)
  • 自定义报告标题和测试环境标识
  • 现代化浅色主题,清晰可读的布局
  • 全屏自适应布局,适配不同尺寸屏幕(小屏自动转为上下布局)

测试结果(左右结构)

  • 参考 Allure 报告的左右结构布局:左侧为测试用例树,右侧为用例详情
  • 点击左侧测试用例后,右侧展示该用例的完整详情
  • 支持 Allure 装饰器(feature/story/title),自动构建层级路径
  • 按功能模块 > 用户故事分组展示,支持展开/折叠
  • 搜索过滤:按名称搜索,按状态筛选
  • 合并显示位置字段:文件路径>类名>方法名

执行过程(Execution)

  • 每个测试用例的执行过程按阶段分组展示:
    • 前置处理(Set up):fixture 中 yield 之前的步骤
    • 测试步骤(Test Body):测试用例主体执行过程
    • 后置处理(Tear down):fixture 中 yield 之后的步骤
  • fixture 无嵌套内容时不显示展开箭头,有内容时可点击展开
  • pure.step 步骤可点击展开,显示该步骤执行期间捕获的日志和附件

媒体支持

  • 支持测试截图,支持缩略图预览和大图查看(可配置 always/fail_only/never)
  • 支持测试录屏,支持在线播放(可配置 always/fail_only/never)
  • 支持 Playwright Trace 录制与可视化回放(可配置 always/fail_only/never)
    • 按用例独立录制,每个用例生成一个 trace zip 文件
    • 报告中每个用例卡片下显示「🎬 Trace 记录」区段(无 trace 时自动隐藏)
    • 点击「查看 Trace」按钮在新标签页打开 Playwright Trace Viewer,可前后穿梭于测试每个操作,直观查看页面快照、DOM、网络请求、控制台日志等
    • 自动复制 Playwright 自带 Trace Viewer SPA 资源到报告目录,支持离线查看

交互功能

  • 返回顶部按钮,方便快速导航
  • 失败用例显示完整错误堆栈和执行原因

pure 公共 API(推荐使用)

  • 完全参考 allure 的 API 设计,提供装饰器、上下文管理器和动态函数
  • 操作步骤:通过 pure.step 记录步骤(自动捕获异常状态、自动识别阶段、自动捕获步骤级日志和附件)
  • 断言结果:在原生 assert 后调用 pure.record* 即可在报告中展示
  • 附件:通过 pure.attach 添加文本/JSON/图片等附件(自动关联到当前步骤)
  • 标签:通过 pure.feature / pure.story / pure.severity 等装饰器添加标签(用于层级分组,不在详情中单独展示)
  • 用法简单、零侵入,不调用也不会影响测试执行

安装

# 从本地安装(开发模式)
cd pytest-pure-report
pip install -e .

# 或者从 PyPI 安装(如果已发布)
pip install pytest-pure-report

快速开始

基本使用

安装插件后,运行 pytest 时会自动生成报告:

pytest test_cases/

指定报告目录

pytest test_cases/ --report-dir=outputs/reports

指定测试环境

pytest test_cases/ --env=test

支持本地图片路径或远程 URL:

# 使用本地图片
pytest test_cases/ --logo=assets/logo.png

# 使用远程 URL
pytest test_cases/ --logo=https://example.com/logo.png

自定义标题

pytest test_cases/ --title="API 自动化测试报告"

完整示例

pytest test_cases/ \
    --report-dir=outputs/reports \
    --report-filename=test_report.html \
    --env=prod \
    --logo=assets/logo.png \
    --title="自动化测试报告" \
    -v

配置选项

命令行选项

选项 说明 默认值
--report-dir 报告输出目录 pure_report
--report-filename 报告文件名 自动生成时间戳文件名
--env 测试环境标识 test
--logo 自定义 Logo 路径(支持本地文件或 http/https URL) 无
--title 自定义报告标题 自动化测试报告

pytest.ini 配置

在项目根目录创建 pytest.ini 文件:

[pytest]
report_dir = outputs/reports
report_filename = test_report.html
env = test
logo = assets/logo.png
title = 自动化测试报告
screenshot_scope = fail_only
video_scope = never
trace_scope = never

环境变量配置

# 设置测试环境
export TEST_ENV=prod

# ========== 浏览器信息(仅 UI 测试需要设置,接口测试无需设置) ==========
# 注意:浏览器信息为按需显示,只有设置了 BROWSER_TYPE 才会在报告中渲染浏览器行。
# 未设置 BROWSER_TYPE 时(如接口测试),报告将不显示浏览器、模式、分辨率等信息。

# 设置浏览器类型(chromium, firefox, webkit)—— 设置后报告才显示浏览器信息
export BROWSER_TYPE=chromium

# 设置无头模式(true 或 false)—— 未设置时默认为 false(有头模式)
export HEADLESS=true

# 设置浏览器窗口分辨率 —— 未设置时报告不显示分辨率
export BROWSER_WIDTH=1920
export BROWSER_HEIGHT=1080

# ========== 媒体捕获配置 ==========
# 设置截图捕获策略(always/fail_only/never)
export SCREENSHOT_SCOPE=fail_only

# 设置录屏捕获策略(always/fail_only/never)
export VIDEO_SCOPE=never

# 设置 Trace 录制策略(always/fail_only/never)
export TRACE_SCOPE=never

# 设置截图和录屏文件路径
export SCREENSHOT_PATH=/path/to/screenshots
export VIDEO_PATH=/path/to/videos

# 设置 trace 文件路径
export TRACE_PATH=/path/to/traces

# 运行测试
pytest test_cases/

配置优先级

配置项按以下优先级生效(高优先级覆盖低优先级):

命令行参数 > 环境变量 > pytest.ini 配置 > 默认值

截图、录屏和 Trace 配置

配置项 说明 默认值
SCREENSHOT_SCOPE 截图捕获策略 fail_only
VIDEO_SCOPE 录屏捕获策略 never
TRACE_SCOPE Trace 录制策略 never
SCREENSHOT_PATH 截图文件目录 outputs/screenshots
VIDEO_PATH 录屏文件目录 outputs/videos
TRACE_PATH Trace 文件目录 outputs/traces

截图/录屏/Trace 策略说明:

  • always:所有用例都捕获/录制
  • fail_only:仅失败用例捕获/保留(默认截图策略;trace 录制后通过用例会自动删除)
  • never:不捕获/录制

Trace 录制说明

Trace 是 Playwright 提供的测试过程可视化能力,开启后会录制测试执行全过程,打包为 .zip 文件,包含:

录制内容 说明
Snapshots(页面快照) 每个操作后的 DOM 状态,可前后穿梭查看页面在任意时刻的样子
Screenshots(截图) 每个操作自动截图
Network(网络) 所有 HTTP 请求/响应详情(含 headers、body)
Console logs 浏览器控制台输出
Source(源码) 每个操作对应的代码位置(可点击跳转)
Action log(动作日志) 所有 Playwright 操作的时间线(含选择器、耗时、错误)

按用例录制:每个用例独立录制一个 trace zip 文件,文件按用例名分子目录存储:

traces/
├── test_login_success/
│   └── test_login_success_1790662054676.zip
├── test_enter_via_avatar_click/
│   └── test_enter_via_avatar_click_1790662059536.zip

报告集成:报告中每个用例卡片下会显示「🎬 Trace 记录」区段(绿色背景),点击「查看 Trace」按钮在新标签页打开 Playwright Trace Viewer 进行可视化回放。

Trace Viewer 部署:报告生成时会自动复制 Playwright 自带的 Trace Viewer SPA 资源到报告目录的 trace-viewer/ 子目录,无需额外安装。由于 Trace Viewer 依赖 Service Worker,必须通过 HTTP 服务器访问报告(直接用 file:// 协议打开会显示友好提示):

# 进入报告目录启动 HTTP 服务器
cd outputs/pure_reports/<timestamp>
python -m http.server 8000

# 浏览器访问报告,点击用例卡片下的「查看 Trace」按钮
# http://localhost:8000/test_report_<timestamp>.html

报告结构

整体布局

报告采用全屏自适应布局,主要区域包括:

  • 报告头部:Logo、标题、环境标识
  • 测试结果概览:统计卡片、饼图、堆叠条形图
  • 测试结果区域(左右结构,参考 Allure):
    • 左侧面板:测试用例树(按 feature > story 分组),支持搜索和状态筛选
    • 右侧面板:选中用例的详情面板

用例详情面板

点击左侧测试用例后,右侧展示:

  • 位置:文件路径>类名>方法名
  • 优先级:从 pure.severity 标签提取
  • 结果:passed/failed/error/skipped 等
  • 耗时:用例执行总耗时
  • 参数(Parameters):参数化用例的参数列表(可折叠)
  • 执行过程(Execution):按阶段分组展示
    • 前置处理(Set up):fixture 列表(可展开查看嵌套步骤)
    • 测试步骤(Test Body):pure.step 步骤列表(可展开查看步骤日志/附件)
    • 后置处理(Tear down):fixture 列表(可展开查看嵌套步骤)
  • 断言结果:表格展示断言详情
  • 截图/录屏:按配置展示
  • Trace 记录:按配置展示(开启 trace 时,每个用例独立录制,无 trace 时自动隐藏)
  • 错误信息:失败用例的错误堆栈

测试状态说明

状态含义

  • passed: 正常通过:断言全部成功,无异常,运行完整
  • failed: 断言失败:用例执行完毕,但断言不成立或主动调用 pytest.fail()
  • error: 执行异常:测试未完整运行(setup/teardown/导入/运行时抛出未捕获异常)
  • xfail: 预期失败:标记了 @pytest.mark.xfail,且实际结果确实是失败
  • xpassed: 意外通过:标记了 @pytest.mark.xfail,但实际运行成功了
  • skipped: 主动跳过:通过 @skip/skipif/xfail(condition=True) 跳过,未执行测试体
  • deselected: 收集阶段剔除:被 -k、--ignore、--collect-only 或配置文件过滤,未进入执行流程

统计公式

  • 总用例数(Total) = passed + failed + error + xfail + xpassed + skipped + deselected
  • 已收集用例数(Selected) = passed + failed + error + xfail + xpassed + skipped
  • 有效用例数(Executed) = passed + failed + error
  • 通过率(Pass Rate) = passed / (passed + failed + error) × 100%

示例测试用例

参数化测试用例

import pytest

class TestLogin:
    @pytest.fixture(params=[
        {"name": "登录页面URL正确", "url": "/login"},
        {"name": "用户名输入框存在", "selector": "#username"},
        {"name": "密码输入框存在", "selector": "#password"},
    ])
    def test_case(self, request):
        return request.param

    def test_login_page_load(self, test_case):
        """测试登录页面加载"""
        print(f"测试用例: {test_case['name']}")
        assert True

普通测试用例

import pytest

class TestExample:
    def test_passed(self):
        """测试通过的用例"""
        assert True

    def test_failed(self):
        """测试失败的用例"""
        assert False, "故意失败"

    @pytest.mark.skip(reason="跳过原因")
    def test_skipped(self):
        """测试跳过的用例"""
        assert True

    @pytest.mark.xfail(reason="已知问题")
    def test_xfail(self):
        """预期失败的用例"""
        assert False

    def test_with_logs(self):
        """带有日志输出的用例"""
        print("这是一条输出日志")
        assert True

截图和录屏

在 conftest.py 中配置 page fixture,测试失败时自动捕获截图和录屏:

import os
import time
import pytest

@pytest.fixture(scope="function")
def page():
    """浏览器页面 fixture"""
    from playwright.sync_api import sync_playwright
    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        page = browser.new_page()
        yield page
        browser.close()

@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """测试失败时自动截图"""
    outcome = yield
    report = outcome.get_result()

    if report.when == "call" and report.failed:
        page = item.funcargs.get("page")
        if page:
            screenshot_dir = os.path.join(os.getcwd(), "outputs", "screenshots")
            os.makedirs(screenshot_dir, exist_ok=True)
            screenshot_path = os.path.join(screenshot_dir, f"{item.name}_{int(time.time()*1000)}.png")
            page.screenshot(path=screenshot_path)

使用注意事项

  1. 不使用 -s 参数:为了让报告能够捕获测试中的 print 和 log 输出,请不要使用 -s(禁用输出捕获)参数
  2. 日志配置:确保 pytest 的日志捕获功能正常工作(使用 --log-cli-level 设置日志级别)
  3. 编码问题:报告文件使用 UTF-8 编码,确保测试代码中的中文输出也是 UTF-8 编码
  4. 参数化名称:参数化用例中如果包含 name 字段,将自动作为用例名称显示
  5. 浏览器信息(按需显示):浏览器信息仅在显式设置 BROWSER_TYPE(环境变量或命令行参数)时才在报告中显示。接口测试等不涉及浏览器的场景无需设置,报告将自动隐藏浏览器、模式、分辨率等信息。命令行参数优先级高于环境变量
  6. 执行过程:测试用例的执行过程按「前置处理 / 测试步骤 / 后置处理」三个阶段分组展示。fixture 无嵌套内容时不显示展开箭头;pure.step 步骤可点击展开查看该步骤执行期间捕获的日志和附件
  7. 截图文件名:截图文件名需遵循 <test_name>_<timestamp>.png 格式,报告插件会自动匹配并显示
  8. 录屏文件名:录屏文件名需遵循 <test_name>_<timestamp>.webm 格式,报告插件会自动匹配并显示
  9. Trace 录制:Trace 仅在使用 Playwright 浏览器测试时可用。开启 TRACE_SCOPE 后,每个用例独立录制一个 trace zip 文件,按用例名分子目录存储在 TRACE_PATH 目录下。报告生成时会自动复制 Playwright 自带 Trace Viewer SPA 到 report_dir/trace-viewer/ 子目录,点击用例卡片下的「查看 Trace」按钮可在新标签页打开 Trace Viewer 进行可视化回放。由于 Trace Viewer 依赖 Service Worker,必须通过 HTTP 服务器访问报告(如 python -m http.server 8000),直接用 file:// 协议打开会显示友好提示

pure 公共 API 使用指南

pure 是本插件提供的一套完全参考 allure 的公共 API,用于在报告中展示 操作步骤、断言结果 和 附件。 所有 API 均为可选调用,不写也不影响测试执行。

导入方式

from pytest_pure_report import pure

API 一览

API 作用
pure.step(title) 步骤(装饰器 + 上下文管理器,自动捕获状态、日志和附件)
pure.fixture(name) fixture 装饰器(自动追踪 setup/teardown)
pure.attach(body, ...) 添加附件(文本/JSON/图片等,自动关联到当前步骤)
pure.attach.file(source, ...) 添加文件附件(自动关联到当前步骤)
pure.record(...) 记录一条断言结果(通用 API,pure 扩展)
pure.record_equal(...) 便捷方法:相等断言
pure.record_contains(...) 便捷方法:包含断言
pure.record_visible(...) 便捷方法:元素可见性断言
pure.title(title) 装饰器:用例标题
pure.feature(*names) 装饰器:feature 标签(用于层级分组)
pure.story(*names) 装饰器:story 标签(用于层级分组)
pure.severity(level) 装饰器:优先级
pure.tag(*tags) 装饰器:标签
pure.link(url, name) 装饰器:链接
pure.dynamic 运行时动态信息
pure.severity_level 优先级常量枚举
pure.attachment_type 附件类型常量枚举

1. step(装饰器 + 上下文管理器)

与 allure.step 完全一致,支持两种写法:

from pytest_pure_report import pure

# 上下文管理器
with pure.step("打开登录页面"):
    page.goto("/login")

# 装饰器(自动用函数名作 step 标题,自动提取参数)
@pure.step("输入用户名和密码")
def fill_credentials(page, username, password):
    page.fill("#username", username)
    page.fill("#password", password)

# 装饰器也可以不传参数,使用函数名作标题
@pure.step
def open_login_page(page):
    page.goto("/login")

step 内部自动捕获异常状态:

  • 无异常 → passed
  • AssertionError → failed
  • 其他异常 → broken(并重新抛出)

step 自动识别阶段(setup / call / teardown),无需手动指定:

  • fixture 中 yield 之前 → setup
  • test 函数中 → call
  • fixture 中 yield 之后 → teardown

step 自动捕获步骤级日志和附件:

  • 步骤执行期间通过 loguru 输出的日志自动捕获到 step_data['log']
  • 步骤执行期间通过 pure.attach 添加的附件自动关联到 step_data['attachments']
  • 报告中步骤行可点击展开,显示该步骤的日志和附件
  • 支持嵌套步骤(父步骤的子步骤独立记录)

2. fixture(自动追踪)

与 allure.fixture 一致,装饰 fixture 函数,插件通过 pytest hook 自动追踪阶段:

import pytest
from pytest_pure_report import pure

@pytest.fixture
@pure.fixture("登录")
def login(page):
    with pure.step("打开登录页面"):
        page.goto("/login")
    yield page
    with pure.step("关闭浏览器"):
        page.context.close()

# 也可不传参数
@pytest.fixture
@pure.fixture
def page():
    ...

3. 断言记录(pure 扩展)

与原生 assert 配合,在报告中展示断言对比:

# 通用 API
assert actual == expected
pure.record("描述", actual, expected, type="==")

# 便捷方法(自动判断 passed)
pure.record_equal(page.title(), "GitLink", "验证页面标题")
pure.record_contains(resp.text, "success", "验证响应包含 success")
pure.record_visible(is_visible, "验证元素可见")

4. 附件

与 allure.attach 一致,附件自动关联到当前步骤(如果在 pure.step 上下文内调用):

# 文本附件
pure.attach("hello world", name="问候", attachment_type=pure.attachment_type.TEXT)

# JSON 附件
pure.attach('{"key": "value"}', name="数据", attachment_type=pure.attachment_type.JSON)

# 文件附件
pure.attach.file("path/to/screenshot.png", name="截图")

5. 标签装饰器

与 allure 完全一致,用于测试用例树的层级分组:

@pure.feature("登录")
@pure.story("成功登录")
@pure.severity(pure.severity_level.CRITICAL)
@pure.tag("smoke")
@pure.title("验证用户使用正确账号可以登录")
@pure.link("https://gitlink.org.cn/issue/1", name="issue-1")
def test_login_success(page):
    ...

6. 运行时动态信息(Dynamic)

与 allure.dynamic 一致,在运行时动态修改信息:

def test_something(page):
    pure.dynamic.title("动态标题")
    pure.dynamic.tag("dynamic-tag")
    pure.dynamic.severity(pure.severity_level.BLOCKER)

报告展示效果

  • 执行过程(Execution):按「前置处理(Set up)/ 测试步骤(Test Body)/ 后置处理(Tear down)」分组展示。
    • fixture 行:有嵌套内容时可点击展开,无内容时显示为简单行(不显示展开箭头)
    • pure.step 步骤行:有日志/附件/错误时可点击展开查看详情
    • 每行显示「状态图标、步骤标题、参数、耗时」
  • 断言结果 表格:展示「断言描述、断言类型、预期值、实际值、结果」列,并显示「全部通过 N 条」或「X/N 通过 N 条」汇总
  • 附件:步骤执行期间的附件显示在对应步骤的展开区域内;步骤外的附件显示在所属阶段区段

完整示例

import pytest
from pytest_pure_report import pure

@pure.feature("登录")
class TestLogin:

    @pytest.fixture
    @pure.fixture("登录")
    def login(self, page):
        with pure.step("打开登录页面"):
            page.goto("/login")
        yield page

    @pure.story("成功登录")
    @pure.severity(pure.severity_level.CRITICAL)
    @pure.title("验证用户使用正确账号可以登录")
    def test_login_success(self, page, login):
        with pure.step("验证用户头像可见"):
            is_visible = page.locator(".currentImg").is_visible()
            assert is_visible
            pure.record_visible(is_visible, "验证用户头像可见")

更详细的 API 说明请参考 pure.py 源码文档。

项目结构

pytest-pure-report/
├── pyproject.toml                    # 项目配置文件
├── README.md                         # 项目文档
├── LICENSE                           # 许可证
├── tests/                            # 测试文件
├── images/                           # 图标资源
├── example/                          # 示例文件
│   └── test_report_*.html            # 示例报告
└── src/
    └── pytest_pure_report/
        ├── __init__.py               # 包初始化
        ├── models.py                 # 数据模型(TestResult)
        ├── generator.py              # 报告生成器(HTML 生成)
        ├── pure.py                   # pure 公共 API(step/attach/record 等)
        └── plugin.py                 # pytest 插件(钩子和命令行选项)

开发

本地开发

# 进入项目目录
cd pytest-pure-report

# 安装开发依赖
pip install -e .

# 运行测试(在项目根目录执行)
pytest tests/ -v

# 构建包(可选)
python -m build

许可证

MIT License

贡献

欢迎提交 Issue 和 Pull Request!


pytest-pure-report - 让测试报告更美观、更实用!

Metadata

Release files for pytest-pure-report 1.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pytest-pure-report 1.0.0
File Size Uploaded
pytest_pure_report-1.0.0.tar.gz 77.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-pure-report 1.0.0
File Interpreter ABI Platform
pytest_pure_report-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 148.1 kB

Release files / pytest_pure_report-1.0.0.tar.gz

Download URL pytest_pure_report-1.0.0.tar.gz
Size 77.1 kB
Tags Source
SHA-256 checksum
How to use checksums
3f500334187f370e9c938e92f323d1e256ceffaa41567a3ef519b41c60b6f37d
BLAKE2b-256 checksum
How to use checksums
912b7222ede948bb7d994efa01fba94af024b05143a577aae78eb72afb51347f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.12

Release files / pytest_pure_report-1.0.0-py3-none-any.whl

Download URL pytest_pure_report-1.0.0-py3-none-any.whl
Size 71.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
24ca2b7cecdfc8fe6f53ed0994d409a232a407216e6366bc6a1b6fe2846acb2a
BLAKE2b-256 checksum
How to use checksums
072f7b4dc344ec370d1d6bf2fb27cf8415f8c9c3f24e805a442839fc95650e65
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.12

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page