哇,我有點遲到了,但我最近就遇到了這個問題,我想,我想出了一個更好的解決方案,所以這裏是......
我工作的一個包含有十幾個劇本都與此完全相同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