如何使用pytest的monkeypatch修改__name__属性以测试主程序代码
测试Python模块中
if __name__ == '__main__':分支的解决方案 问题原因
你之前尝试修改builtins.__name__的思路不对——每个Python模块都有自己独立的__name__属性,模块导入时解释器会自动将其设置为模块名(比如你的mymodule),修改全局的builtins.__name__不会影响已导入模块的这个属性,所以无法触发目标分支。
解决方案
以下两种纯pytest兼容的方法可以实现你的需求,且不需要unittest相关工具:
方法1:使用runpy.run_module运行模块
runpy.run_module可以模拟直接执行模块(如同python mymodule.py),能将模块的__name__设为__main__,从而触发目标分支:
# test_mymodule.py import runpy def test_main_branch(): # 运行模块并指定run_name为__main__,预期触发AssertionError runpy.run_module('mymodule', run_name='__main__')
执行测试时,这个用例会因为模块里的assert False而失败,同时覆盖率工具会统计到if __name__ == '__main__':分支的代码。
方法2:修改模块__name__后重新加载
先导入模块,修改其__name__为__main__,再重新加载模块,触发分支代码:
# test_mymodule.py import importlib import mymodule def test_main_branch(): # 修改模块的__name__属性 mymodule.__name__ = '__main__' # 重新加载模块,此时会执行__main__分支代码 importlib.reload(mymodule)
同样,这个测试会因为assert False失败,且覆盖率拉满。
验证覆盖率
运行pytest时加上覆盖率参数:
pytest --cov=mymodule test_mymodule.py
输出会显示mymodule.py的测试覆盖率为100%。
内容的提问来源于stack exchange,提问作者Marcos
相关产品推荐
相关产品推荐

