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
自定义 Logo
支持本地图片路径或远程 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)
使用注意事项
- 不使用 -s 参数:为了让报告能够捕获测试中的 print 和 log 输出,请不要使用
-s(禁用输出捕获)参数 - 日志配置:确保 pytest 的日志捕获功能正常工作(使用
--log-cli-level设置日志级别) - 编码问题:报告文件使用 UTF-8 编码,确保测试代码中的中文输出也是 UTF-8 编码
- 参数化名称:参数化用例中如果包含
name字段,将自动作为用例名称显示 - 浏览器信息(按需显示):浏览器信息仅在显式设置
BROWSER_TYPE(环境变量或命令行参数)时才在报告中显示。接口测试等不涉及浏览器的场景无需设置,报告将自动隐藏浏览器、模式、分辨率等信息。命令行参数优先级高于环境变量 - 执行过程:测试用例的执行过程按「前置处理 / 测试步骤 / 后置处理」三个阶段分组展示。fixture 无嵌套内容时不显示展开箭头;pure.step 步骤可点击展开查看该步骤执行期间捕获的日志和附件
- 截图文件名:截图文件名需遵循
<test_name>_<timestamp>.png格式,报告插件会自动匹配并显示 - 录屏文件名:录屏文件名需遵循
<test_name>_<timestamp>.webm格式,报告插件会自动匹配并显示 - 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)
| File | Size | Uploaded | |
|---|---|---|---|
| pytest_pure_report-1.0.0.tar.gz | 77.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|