Reputation: 170410
As tests can be enabled or disabled automatically based on existing environment there is always the risk that something in CI is changed that makes pytest skip tests when they were not supposed to.
If I could define a minimum number of tests, or maybe even a fixed number of expected tests in an environment variable I could prevent accidents where CI passes just because tests were skipped.
Most of the time pytest is called by tox, which is also used in development environments. This means that the expected number of tests must be defined in CI config (like .travis.yml
), because this is the only place which is specific to CI.
Upvotes: 1
Views: 1087
Reputation: 66231
You can add a custom hook impl and count the amount of passed tests. After the test run finishes, check the counter and exit with a custom exit code if the amount of tests passed was too low. Example: add the code to your 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}')
This adds a new command line option --minpass
that expects a minimal amount of tests required for the run to succeed; the default value is zero so it shouldn't affect any existing suites if not provided. session.exitstatus = 127
sets the custom exit code; change it to whatever code you need. The pytest_sessionfinish
hook uses the terminal reporter to display the error in a custom section; change the output to whatever format you need.
A sample execution with at least one test to pass yields:
$ 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
If you want to support the environment variables, adapt the pytest_sessionfinish
hook impl with e.g.
def pytest_sessionfinish(session, exitstatus):
min_passed = session.config.getoption('minpass') or int(os.environ.get('PYTEST_MINPASS', '0'))
...
and set the PYTEST_MINPASS
environment variable to turn on the check.
Upvotes: 2