求助:pytest-cov检测多模块覆盖率未达阈值时返回0退出码的问题
求助:pytest-cov检测多模块覆盖率未达阈值时返回0退出码的问题
我最近碰到了pytest-cov的一个离谱问题:当多个模块的平均测试覆盖率没达到设定阈值时,控制台明明会输出"未达标"的提示,但pytest居然返回0退出码,直接导致我的CI/CD流水线通过,把低覆盖率的代码合并到主分支了,这可太坑了!
先讲下我的具体场景:
我执行的命令是:
pytest --cov module1 --cov module2 --cov module3 --cov-report term --cov-fail-under=75
控制台会正确输出覆盖率未达标的提示:
FAIL Required test coverage of 75.0% not reached. Total coverage: 74.79%
但紧接着执行echo $?,得到的结果却是0——完全没触发CI的失败机制。
我已经试过好几种方案,都没能解决问题:
- 尝试把多个模块合并成一个参数
--cov=module1,module2,module3,结果直接报错CoverageWarning: Module module1,module2,module3 was never imported,它把逗号分隔的内容当成了单个模块名,根本识别不了是三个独立模块。 - 把需要检测的模块列表写到
pyproject.toml的[tool.coverage.run]的include字段里,结果还是老样子:控制台提示未达标,但退出码依旧是0。
有意思的是,如果单独对每个模块跑测试,比如只测module1,只要它的覆盖率不够,pytest会正常返回非0退出码,完全没问题。
我在网上搜了一圈,没找到能解决的方案,Copilot给的建议也没什么用。
更新:已复现问题,找到疑似根源
我做了一个最小可复现示例(MWE),终于发现问题出在覆盖率的四舍五入逻辑上!
比如我设置阈值为67%,实际总覆盖率是66.66%,控制台会正确提示:
FAIL Required test coverage of 67% not reached. Total coverage: 66.67%
但退出码居然还是0!看起来pytest-cov的退出码判断逻辑,可能是用了四舍五入后的整数覆盖率来和阈值比较——比如66.66%四舍五入后是67%,刚好等于阈值,就返回了0?这完全是逻辑bug啊!
有没有大佬遇到过这个问题?或者知道怎么解决吗?




