哇,我有点迟到了,但我最近就遇到了这个问题,我想,我想出了一个更好的解决方案,所以这里是......
我工作的一个包含有十几个剧本都与此完全相同copypasta结束模块:
if __name__ == '__main__':
if '--help' in sys.argv or '-h' in sys.argv:
print(__doc__)
else:
sys.exit(main())
不可怕,肯定的,但不可测试无论是。我的解决办法是在我的模块中的一个写一个新功能:
def run_script(name, doc, main):
"""Act like a script if we were invoked like a script."""
if name == '__main__':
if '--help' in sys.argv or '-h' in sys.argv:
sys.stdout.write(doc)
else:
sys.exit(main())
,然后把这种宝石在每个脚本文件的末尾:
run_script(__name__, __doc__, main)
从技术上讲,此功能将无条件是否运行您的脚本作为模块导入或作为脚本运行。这是好的,但因为该功能实际上并不做任何东西,除非该脚本正在作为脚本运行。因此,代码覆盖率看到函数运行,并说“是的,100%的代码覆盖率!”同时,我写了三个测试覆盖本身的功能:
@patch('mymodule.utils.sys')
def test_run_script_as_import(self, sysMock):
"""The run_script() func is a NOP when name != __main__."""
mainMock = Mock()
sysMock.argv = []
run_script('some_module', 'docdocdoc', mainMock)
self.assertEqual(mainMock.mock_calls, [])
self.assertEqual(sysMock.exit.mock_calls, [])
self.assertEqual(sysMock.stdout.write.mock_calls, [])
@patch('mymodule.utils.sys')
def test_run_script_as_script(self, sysMock):
"""Invoke main() when run as a script."""
mainMock = Mock()
sysMock.argv = []
run_script('__main__', 'docdocdoc', mainMock)
mainMock.assert_called_once_with()
sysMock.exit.assert_called_once_with(mainMock())
self.assertEqual(sysMock.stdout.write.mock_calls, [])
@patch('mymodule.utils.sys')
def test_run_script_with_help(self, sysMock):
"""Print help when the user asks for help."""
mainMock = Mock()
for h in ('-h', '--help'):
sysMock.argv = [h]
run_script('__main__', h*5, mainMock)
self.assertEqual(mainMock.mock_calls, [])
self.assertEqual(sysMock.exit.mock_calls, [])
sysMock.stdout.write.assert_called_with(h*5)
布拉姆!现在您可以编写一个可测试的main()
,将其作为脚本调用,具有100%的测试覆盖率,并且不需要忽略覆盖报告中的任何代码。
Heya,我已经添加了一个新的答案,提供100%的测试覆盖率(测试!),并且不需要忽略任何东西。让我知道你的想法:http://stackoverflow.com/a/27084447/1423157谢谢。 – robru 2014-11-23 23:59:38
对于那些想知道:'nose-cov'在下面使用coverage.py,所以具有上述内容的'.coveragerc'文件将工作得很好。 – Joscha 2015-11-12 04:58:37
恕我直言,即使我发现它有趣和有用,这个答案不*实际给予OP的回应。他想要测试主叫,不要跳过这个检查。否则,脚本实际上可以完成除了实际预期的任何事情以外的所有事情,并且测试会显示“OK,一切正常!”。主要功能可以完全通过单元测试,即使从未被实际调用过。 – iacopo 2017-02-05 10:25:24