前言
除了失败立即 retry,有时我们也需要在开发修复后单独重跑失败的用例。 介于 pytest 可以手动指定 n 条用例目录,所以实现起来并不难。
举个例子
python testcase/feat_a/test_a.py::CaseClassATest
python testcase/feat_a/test_a.py::CaseClassATest testcase/feat_b/test_b.py::CaseClassBTest
1. 每次执行用例时,收集失败的用例路径
pytest 用例执行失败后提供了失败用例的路径,格式可以直接使用。 testcase/xxxxxxx/login/user_login_with_phone_test.py::UserLoginWithPhoneTest
conftest.py
@pytest.hookimpl(hookwrapper=True)
def pytest_runtest_makereport(item, call):
"""
每条用例运行过程中的特殊处理。执行 n 遍,每遍执行3次,分别是 setup、call、teardown。
"""
outcome = yield
report = outcome.get_result()
if report.when == "call" and report.failed:
'''
省去其他无关代码
'''
failed_testcase = '::'.join(report.nodeid.split('::')[:2])
if 'FAILED_TESTCASES' in os.environ:
if failed_testcase not in os.environ['FAILED_TESTCASES']:
os.environ['FAILED_TESTCASES'] += ' ' + failed_testcase
else:
os.environ['FAILED_TESTCASES'] = failed_testcase
* 这里我用了环境变量来存放,实际上用一个字符串变量来存放也可以。 * 如果要精确到函数需要注意 parametrize 注解会导致路径最后有 [] 参数部分。
2. 将收集的失败用例写入文件
这里我写入的是 output 目录,因为我gitlab ci 使用 artifacts 参数保留了这个目录 也可以放入 cache 目录,用于 ci job 之间的共享(或传递)
conftest.py
@pytest.mark.optionalhook
def pytest_html_report_title(report):
"""
pytest-html 系列钩子
"""
'''
省去其他无关代码
'''
from common.config import Config
if 'FAILED_TESTCASES' in os.environ:
with open(f'{Config().get_root_dir()}/output/failed-testcases.txt', 'w') as f:
f.write(os.environ['FAILED_TESTCASES'])
3. GitLab CI 执行失败用例
使用 pytest $(cat output/failed-testcases.txt) 可以动态执行文件中收集的失败测试用例 使用 artifacts 目录来存放 failed-testcaes.txt 的话,重跑 job 必须在 测试 job 后面的阶段。 使用 cache 目录来存放 failed-testcaes.txt 的话,理论上重跑 job 和测试 job 可以在同一阶段。
gitlab-ci.yml
retry-test:
stage: report
extends: .with-tags
artifacts:
name: '$CI_COMMIT_REF_SLUG'
paths:
- output/
when: on_failure
script:
- |
if [[ -f "output/failed-testcases.txt" ]]; then
python3 -m poetry run pytest $(cat output/failed-testcases.txt) -s -v --env $RUN_ENVIRONMENT --reruns 1 --reruns-delay 3 --html=./output/report.html --self-contained-html
fi
when: on_failure
目前还有一点问题就是,我只能使用 on_failure 来触发 job。这导致 重跑 job 肯定会执行一遍。 理想情况下我希望 前置 job 失败、或者存在 failed-testcases.txt 文件,才出现 job 图标,然后 manual 方式执行。但是经过一番尝试,仍然没有实现。
- when 参数的 on_faiulre 和 manual 不能共存。并且设置 when manual 后,如果前置 job 失败, 后置 job 就会 skip
- rules exists 来判断文件存在也没有起效,可能判断触发条件时,测试 job 还未执行所以没有文件。
演示
测试 job 执行失败后,失败用例列表写入 failed-testcases.txt 文件,并存入 artifacts 中 重跑 job 每次都从 artifacts 目录中读取 failed-testcases.txt 文件中的 失败用例列表来执行
|