Skip to main content

pytest-testcase-collector

一个 pytest 插件,可自动收集测试用例报告数据(名称、级别、类型、所属类/模块、代码仓等),并生成指定格式的 XML 文件。

核心功能

  1. 元数据采集:提取用例名称、级别(@pytest.mark.case_info(level))、类型(@pytest.mark.case_info(type))、所属类/模块信息,支持参数化用例
  2. Git 信息集成:自动识别 Git 仓库,获取仓库 URL、分支信息(非 Git 仓库自动兼容)
  3. XML 生成:按固定结构生成包含流水线/任务标识的 XML 元数据文件
  4. Flaky 重试支持:支持标记不稳定测试用例进行自动重试,满足最小通过次数要求
  5. 环境变量控制:支持通过环境变量控制 JUnit XML 输出和元数据收集行为
  6. 灵活配置:支持命令行指定输出路径、流水线 ID 等参数,提供完善的错误处理

快速开始

1. 安装插件

方式 1:从 whl 包安装(推荐)

# 先构建 whl 包(需提前安装 build 模块)
pip install build
python -m build --wheel

# 安装生成的whl包
pip install dist/pytest_report_uploader-1.0.0-py3-none-any.whl

方式 2:源码开发模式安装

pip install -e .

2. 使用示例

仅收集用例 + 生成元数据(推荐)

pytest test_first.py --pipeline-id 123456 --pipeline-run-id 789012 --job-id 345678 --collect-only

运行测试 + 生成元数据

pytest test_first.py --pipeline-id 123456 --pipeline-run-id 789012 --job-id 345678

使用环境变量控制行为

# 启用自动 JUnit XML 输出
export ENABLE_JUNITXML_OUTPUT=1
export RESULTS_XML_DIR=./test-results
pytest test_first.py

# 禁用元数据收集
export DISABLE_METADATA_COLLECTION=1
pytest test_first.py

3. 命令行参数说明

所有参数均为可选,未指定则对应字段留空

参数 说明 默认值
--pipeline-id 流水线唯一标识
--pipeline-run-id 流水线运行记录 ID
--job-id 任务/作业唯一标识
--metadata-output 元数据 XML 输出文件路径 metadata.xml

4. 环境变量说明

环境变量 说明 默认值
ENABLE_JUNITXML_OUTPUT 设置为 1/true/yes 时自动添加 --junitxml 参数 不启用
RESULTS_XML_DIR JUnit XML 输出目录 results_xml_dir
DISABLE_METADATA_COLLECTION 设置为 1/true/yes 时禁用元数据收集和 XML 生成 启用

Flaky 测试重试

使用方式

import pytest


@pytest.mark.flaky(reruns=3, reruns_delay=2, min_pass=2)
def test_flaky_test():
    """不稳定的测试用例,最多重试3次,每次间隔2秒,至少通过2次"""
    import random

    assert random.choice([True, False, True])

参数说明

参数 说明 默认值
reruns 重试次数 1
reruns_delay 重试间隔(秒) 0
min_pass 最小通过次数(需同时设置 reruns > 0) 1

注意:只有同时设置 reruns > 0min_pass > 0 时,才会启用自定义重试逻辑。

示例展示

测试用例示例

import pytest


@pytest.mark.case_info(level="L0", type="Functional")
def test_first():
    assert 1 == 1


@pytest.mark.case_info(level="L1", type="Functional")
@pytest.mark.parametrize("a,b", [("3+5", 8), ("3+2", 5)])
def test_second(a, b):
    assert eval(a) == b


@pytest.mark.flaky(reruns=3, min_pass=2)
def test_flaky_example():
    import random

    assert random.choice([True, False])

生成的 XML 示例

<?xml version='1.0' encoding='utf-8'?>
<metadata>
    <pipelineId>123456</pipelineId>
    <pipelineRunId>789012</pipelineRunId>
    <jobId>345678</jobId>
    <frameType>pytest</frameType>
    <repoUrl>https://gitcode.com/openlibing/openlibing-pytest-executor.git</repoUrl>
    <repoBranch>main</repoBranch>
    <testCases>
        <testCase>
            <name>test_first</name>
            <level>L0</level>
            <type>Functional</type>
            <className>test_first</className>
            <filePath>test_first.py</filePath>
        </testCase>
        <testCase>
            <name>test_second[3+5-8]</name>
            <level>L1</level>
            <type>Functional</type>
            <className>test_first</className>
            <filePath>test_first.py</filePath>
        </testCase>
        <testCase>
            <name>test_second[3+2-5]</name>
            <level>L1</level>
            <type>Functional</type>
            <className>test_first</className>
            <filePath>test_first.py</filePath>
        </testCase>
    </testCases>
</metadata>

技术架构

整体流程

命令行参数处理 → 测试用例收集 → 元数据提取 → Git 仓库信息获取 → XML 文件生成 → 测试执行(支持 flaky 重试)→ JUnit XML 修改

项目结构

pytest-testcase-collector/
├── pytest_testcase_collector/     # 插件主包
│   ├── __init__.py                # 包初始化
│   ├── conftest.py                # pytest 钩子实现(核心)
│   ├── metadata_collector.py      # 元数据收集核心逻辑
│   ├── flaky_rerun.py             # flaky 用例重试处理
│   ├── git_info.py                # Git 信息获取
│   ├── xml_generator.py           # XML 生成
│   └── error_handler.py           # 错误处理
├── test_first.py                  # 测试示例
├── readMe.md                      # 说明文档
├── setup.py                       # 安装配置
├── pyproject.toml                 # 依赖与元数据管理
└── pytest.ini                     # pytest 配置

核心钩子函数

函数 作用 执行时机
pytest_load_initial_conftests 根据环境变量添加 --junitxml 参数 命令行参数解析后,插件初始化前
pytest_sessionstart 初始化元数据存储 测试会话开始时
pytest_collection_modifyitems 收集每个测试用例的元数据 测试用例收集完成后
pytest_collection_finish 生成元数据 XML 文件 测试用例收集完成后
pytest_runtest_protocol 处理 flaky 测试重试逻辑 每个测试用例执行前
pytest_sessionfinish 修改 JUnit XML 添加 flaky 标识 测试会话结束时

错误处理

插件内置完善的异常处理机制:

  • 元数据提取失败:输出明确的错误提示,不中断整体流程
  • XML 生成失败:记录详细日志并提示可能的原因(如路径无写入权限)
  • Git 信息获取失败:自动跳过并将 repoUrl/repoBranch 置空,兼容非 Git 环境
  • Flaky 重试失败:记录重试次数和结果,不影响其他测试执行

注意事项

  1. 使用 --collect-only 参数时,仅收集用例元数据,不执行测试
  2. 元数据收集默认启用,可通过 DISABLE_METADATA_COLLECTION=1 禁用
  3. JUnit XML 输出默认关闭,可通过 ENABLE_JUNITXML_OUTPUT=1 启用
  4. Flaky 重试需要同时设置 reruns > 0min_pass > 0 才会生效

Release files for pytest-testcase-collector 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-testcase-collector 1.0.0
File Size Uploaded
pytest_testcase_collector-1.0.0.tar.gz 17.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pytest-testcase-collector 1.0.0
File Interpreter ABI Platform
pytest_testcase_collector-1.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 33.7 kB

Release files / pytest_testcase_collector-1.0.0.tar.gz

Download URL pytest_testcase_collector-1.0.0.tar.gz
Size 17.1 kB
Tags Source
SHA-256 checksum
How to use checksums
0cc105e98450943510d4e2620162d9fabc2ad98d1be49b71e4eb8f585caf88d2
BLAKE2b-256 checksum
How to use checksums
65a36316eff1a6bf4f563e1839f5d5f20ffe45140386a8829593d1f5b9986058
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.12

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

Download URL pytest_testcase_collector-1.0.0-py3-none-any.whl
Size 16.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fc6ba4a79c61159b1883e8f8de2fb03ba523626d7e2c6462fd0f6c07a6d19ce7
BLAKE2b-256 checksum
How to use checksums
304aa06f0d4c973f99d7d570a4d8fb1106811ab189b0c09c8c98147d6b744e1e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.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