Pytest + GitLab CI 单独重跑失败的用例

前言

除了失败立即 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.mark.optionalhook
def pytest_html_results_table_row(report, cells):
    """
    pytest-html,自定义每条用例的测试结果的的特殊处理。执行 n 遍,只有 call 阶段会执行。可用于修改报告的列数据。

    """
   	''' 
   	省去其他无关代码
    '''
    
    # 保收集失败用例路径
    if report.outcome == '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

* 放在这个 hook 是为了区分 rerun 和 failed,放在 pytest_runtest_makereport hook 中无法区分。
* 这里我用了环境变量来存放,实际上用一个字符串变量来存放也可以。
* 如果要精确到函数需要注意 parametrize 注解会导致路径最后有 [] 参数部分。

2. 将收集的失败用例列表写入文件

这里我写入的是 output 目录,因为我gitlab ci 使用 artifacts 参数保留了这个目录
也可以放入 cache 目录,用于 ci job 之间的共享(或传递)

conftest.py

@pytest.mark.optionalhook
def pytest_html_report_title(report):
    """
    pytest-html 系列钩子,执行 1 遍。
    """

   	''' 
   	省去其他无关代码
   	'''

    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 文件中的 失败用例列表来执行
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值