You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测未标记的pytest测试?构建CI脚本实现告警或报错

检测未标记的Pytest测试用例并集成到CI

方法1:用pytest收集+脚本分析

通过pytest的--collect-only功能导出所有测试的元数据,再用脚本筛选出没有自定义分组标记的测试,最终在CI中抛出错误终止流程。

步骤1:编写检测脚本(check_unmarked_tests.py)

import subprocess
import sys
import json

# 调用pytest收集所有测试并输出为JSON格式
collect_result = subprocess.run(
    ["pytest", "--collect-only", "-q", "--tb=no", "--json-report"],
    capture_output=True,
    text=True
)

if collect_result.returncode != 0:
    print("收集测试用例失败:", collect_result.stderr)
    sys.exit(1)

test_data = json.loads(collect_result.stdout)
unmarked_tests = []

# 定义内置标记(这些不算作你的分组标记,需要排除)
builtin_marks = {"parametrize", "skip", "xfail", "skipif", "usefixtures"}

# 遍历所有测试,检查是否有自定义分组标记
for test_item in test_data["tests"]:
    test_marks = set(test_item.get("marks", []))
    custom_group_marks = test_marks - builtin_marks
    if not custom_group_marks:
        unmarked_tests.append(test_item["nodeid"])

# 根据检查结果输出信息并设置退出码
if unmarked_tests:
    print("错误:发现未标记的测试用例(这些测试不会在CI中执行):")
    for test in unmarked_tests:
        print(f"  - {test}")
    sys.exit(1)
else:
    print("所有测试用例均已配置有效分组标记。")
    sys.exit(0)

步骤2:集成到GitHub Actions

在你的CI workflow文件(比如.github/workflows/check-unmarked-tests.yml)中添加如下Job:

name: 检查未标记测试用例
on: [pull_request, push]

jobs:
  check-unmarked:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: 配置Python环境
        uses: actions/setup-python@v5
        with:
          python-version: "3.x"
      - name: 安装依赖
        run: |
          python -m pip install --upgrade pip
          pip install pytest pytest-json-report
      - name: 执行未标记测试检查
        run: python check_unmarked_tests.py

方法2:用pytest钩子自定义检查

编写一个极简的pytest插件,在测试收集阶段直接检查标记,无需额外脚本。

编写pytest插件(pytest_enforce_marks.py)

def pytest_collection_modifyitems(config, items):
    builtin_marks = {"parametrize", "skip", "xfail", "skipif", "usefixtures"}
    unmarked_tests = []
    
    for item in items:
        # 获取当前测试的所有标记名称
        test_mark_names = set(mark.name for mark in item.iter_markers())
        custom_group_marks = test_mark_names - builtin_marks
        if not custom_group_marks:
            unmarked_tests.append(item.nodeid)
    
    if unmarked_tests:
        config.stderr.write("错误:检测到未标记的测试用例:\n")
        for test in unmarked_tests:
            config.stderr.write(f"  {test}\n")
        raise SystemExit(1)

在CI中使用插件

直接通过pytest命令加载插件并执行检查:

pytest -p pytest_enforce_marks.py --collect-only

额外提示

  • 如果存在无需分组的特殊测试(比如基础工具类测试),可以添加一个allow_unmarked标记,在检查逻辑中排除带有该标记的测试。
  • 建议将检查放在PR触发的CI流程中,提前拦截未标记的测试,避免合并后出现测试遗漏。

内容的提问来源于stack exchange,提问作者Stalin Thomas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 02:22:46