由于测试可以根据现有环境自动启用或禁用,因此始终存在 CI 中某些内容发生更改的风险,从而使 pytest 在不应该进行的测试时跳过测试。
如果我可以在环境变量中定义最小数量的测试,或者甚至是固定数量的预期测试,我就可以防止 CI 通过仅仅因为测试被跳过而发生的事故。
大多数时候pytest是由tox调用的,tox也用在开发环境中。这意味着预期的测试数量必须在 CI 配置中定义(如 .travis.yml
),因为这是唯一特定于 CI 的地方。
最佳答案
您可以添加自定义钩子(Hook)实现并计算通过的测试数量。测试运行完成后,检查计数器,如果通过的测试量太低,则使用自定义退出代码退出。示例:将代码添加到您的 conftest.py
中:
import pytest
def pytest_addoption(parser):
parser.addoption('--minpass', type=int, default=0, help='minimum amount of tests to pass')
def pytest_sessionstart(session):
session.count_passed = 0
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
result = outcome.get_result()
if result.when == 'call' and result.passed:
item.session.count_passed += 1
def pytest_sessionfinish(session, exitstatus):
min_passed = session.config.getoption('minpass')
if session.count_passed < min_passed:
session.exitstatus = 127
reporter = session.config.pluginmanager.get_plugin('terminalreporter')
reporter.section('Session errors', sep='-', red=True, bold=True)
reporter.line(f'Not enough successful tests - expected at least {min_passed} to pass, passed {session.count_passed}')
这添加了一个新的命令行选项--minpass
,它期望运行成功所需的最少测试量;默认值为零,因此如果未提供,它不会影响任何现有套件。 session.exitstatus = 127
设置自定义退出代码;将其更改为您需要的任何代码。 pytest_sessionfinish
Hook 使用终端报告器在自定义部分中显示错误;将输出更改为您需要的任何格式。
至少有一项测试能够通过 yield 的示例执行:
$ pytest --minpass 1
======================================= test session starts ========================================
platform linux -- Python 3.6.9, pytest-5.3.1, py-1.8.0, pluggy-0.13.0
rootdir: /home/hoefling/projects/private/stackoverflow/so-59116898
plugins: mock-1.11.0, xdist-1.29.0, asyncio-0.10.0, forked-1.0.2, cov-2.8.1, testinfra-3.2.0
collected 1 item
test_spam.py s [100%]
------------------------------------------ Session errors ------------------------------------------
Not enough successful tests - expected at least 1 to pass, passed 0
======================================== 1 skipped in 0.01s ========================================
$ echo $?
127
如果您想支持环境变量,请调整 pytest_sessionfinish
钩子(Hook)实现,例如
def pytest_sessionfinish(session, exitstatus):
min_passed = session.config.getoption('minpass') or int(os.environ.get('PYTEST_MINPASS', '0'))
...
并设置PYTEST_MINPASS
环境变量以打开检查。
关于python - 如果未运行最小数量的测试,如何使 pytest 返回失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59116898/