Summary
Expected vs actual result
When the average test coverage threshold across multiple modules isn't met, pytest doesn't fail with a non-zero exit code, even though it should.
Reproducer
Versions
OS and hardware
Model Name: MacBook Pro
Model Identifier: Mac16,5
Chip: Apple M4 Max
System Version: macOS 15.6 (24G84)
Kernel Version: Darwin 24.6.0
Pytest versions
pytest = "^8.3.4"
pytest-cov = "^6.0.0"
Config
In pyproject.toml:
[tool.coverage.run]
branch = true
[tool.coverage.report]
fail_under = 75
exclude_lines = ['pragma: no cover', 'raise NotImplementedError', '\s*\.\.\.']
[tool.coverage.html]
directory = './coverage'
[tool.coverage.xml]
output = './coverage/cov.xml'
Code
My command:
❯ pytest --cov module1 --cov module2 --cov module3 --cov-report --cov-fail-under=75
I get the following result:
FAIL Required test coverage of 75.0% not reached. Total coverage: 74.79%
But the exit code remains zero:
As a result, my CI/CD pipeline (triggered upon a PR to main) passes just fine even though my coverage threshold isn't met. This causes my main branch to have too low test coverage.
I've tried
- Passing
--cov=module1,module2,module3 instead of having one pytest call with three different --cov arguments. This causes the coverage report to fail altogether, because it says that CoverageWarning: Module module1,module2,module3 was never imported. I.e., it tries to import module1,module2,module3 as a single module and it fails, since they are separate modules.
- Passing the to-be-included modules in
pyproject.toml under [tool.coverage.run] in the include argument. Problem persists: test coverage threshold failure is noted, but exit code is zero.
- Interestingly, when you test on each of the modules individually, you do get a non-zero exit code for the module that has too low coverage.
- On the internet, I can't really seem to find a working solution. Copilot isn't very useful here either.
Summary
Expected vs actual result
When the average test coverage threshold across multiple modules isn't met, pytest doesn't fail with a non-zero exit code, even though it should.
Reproducer
Versions
OS and hardware
Pytest versions
Config
In
pyproject.toml:Code
My command:
I get the following result:
But the exit code remains zero:
As a result, my CI/CD pipeline (triggered upon a PR to
main) passes just fine even though my coverage threshold isn't met. This causes mymainbranch to have too low test coverage.I've tried
--cov=module1,module2,module3instead of having one pytest call with three different--covarguments. This causes the coverage report to fail altogether, because it says thatCoverageWarning: Module module1,module2,module3 was never imported. I.e., it tries to importmodule1,module2,module3as a single module and it fails, since they are separate modules.pyproject.tomlunder[tool.coverage.run]in theincludeargument. Problem persists: test coverage threshold failure is noted, but exit code is zero.