我正在尝试对一些看起来像这样的代码进行单元测试:
def main():
parser = optparse.OptionParser(description='This tool is cool', prog='cool-tool')
parser.add_option('--foo', action='store', help='The foo option is self-explanatory')
options, arguments = parser.parse_args()
if not options.foo:
parser.error('--foo option is required')
print "Your foo is %s." % options.foo
return 0
if __name__ == '__main__':
sys.exit(main())
使用如下代码:
@patch('optparse.OptionParser')
def test_main_with_missing_p4clientsdir_option(self, mock_optionparser):
#
# setup
#
optionparser_mock = Mock()
mock_optionparser.return_value = optionparser_mock
options_stub = Mock()
options_stub.foo = None
optionparser_mock.parse_args.return_value = (options_stub, sentinel.arguments)
def parser_error_mock(message):
self.assertEquals(message, '--foo option is required')
sys.exit(2)
optionparser_mock.error = parser_error_mock
#
# exercise & verify
#
self.assertEquals(sut.main(), 2)
我正在使用Michael Foord's Mock和鼻子来运行测试。
当我进行测试时,我得到:
File "/Users/dspitzer/Programming/Python/test-optparse-error/tests/sut_tests.py", line 27, in parser_error_mock
sys.exit(2)
SystemExit: 2
----------------------------------------------------------------------
Ran 1 test in 0.012s
FAILED (errors=1)
问题是OptionParser.error执行sys.exit(2),因此main()自然依赖于它。但是nose或unittest检测到(预期的)sys.exit(2)并且未通过测试。
我可以通过在main()中的parser.error()调用下添加“return 2”并从parser_error_mock()中删除sys.exit()调试来进行测试,但是我觉得修改代码很令人讨厌在测试中允许测试通过。有更好的解决方案吗?
更新:df的答案有效,但正确的调用是“self.assertRaises(SystemExit,sut.main)”。
这意味着测试会传递parser_error_mock()中sys.exit()中的数字。有没有办法测试退出代码?
顺便说一句,如果我补充一下,测试会更加强大:self.assertEquals(optionparser_mock.method_calls, [('add_option', ('--foo',), {'action': 'store', 'help': 'The foo option is self-explanatory'}), ('parse_args', (), {})])
最后。
更新2 :我可以通过将“self.assertRaises(SystemExit,sut.main)”替换为:
来测试退出代码try:
sut.main()
except SystemExit, e:
self.assertEquals(type(e), type(SystemExit()))
self.assertEquals(e.code, 2)
except Exception, e:
self.fail('unexpected exception: %s' % e)
else:
self.fail('SystemExit exception expected')
答案 0 :(得分:12)
这是否有效而不是assertEquals
?
self.assertRaises(SystemExit, sut.main, 2)
这应该捕获SystemExit
异常并阻止脚本终止。
答案 1 :(得分:1)
正如我对我的问题的更新中所述,我不得不修改dF的答案:
self.assertRaises(SystemExit, sut.main)
...我想出了一些更长的片段来测试退出代码。
[注意:我接受了我自己的回答,但如果他更新了他,我会删除这个答案并接受dF。]
答案 2 :(得分:0)
这个问题可能包含一些新信息:
答案 3 :(得分:0)
将@raises
添加到测试功能中。即:
from nose.tools import raises
@raises(SystemExit)
@patch('optparse.OptionParser')
def test_main_with_missing_p4clientsdir_option(self, mock_optionparser):
# Setup
...
sut.main()