在Python中从单元测试输出数据

139 投票
14 回答
186215 浏览
提问于 2025-04-11 17:56

如果我在用Python写单元测试(使用unittest模块),我能否在测试失败时输出一些数据,这样我就可以检查这些数据,帮助我找出错误的原因?

我知道可以创建一个自定义的消息,里面可以包含一些信息,但有时候你可能会处理更复杂的数据,这些数据不容易用字符串表示。

比如,假设你有一个叫Foo的类,并且在测试一个叫bar的方法,使用的数据来自一个叫testdata的列表:

class TestBar(unittest.TestCase):
    def runTest(self):
        for t1, t2 in testdata:
            f = Foo(t1)
            self.assertEqual(f.bar(t2), 2)

如果测试失败了,我可能想输出t1、t2和/或f,看看为什么这些特定的数据导致了失败。这里的输出是指,在测试运行后,这些变量可以像其他变量一样被访问。

14 个回答

34

你可以使用简单的打印语句,或者其他任何方式来输出信息到标准输出。你也可以在测试的任何地方调用Python调试器。

如果你使用 nose 来运行你的测试(我推荐这样做),它会收集每个测试的标准输出,只有在测试失败时才会显示给你,这样在测试通过时你就不会看到杂乱的输出了。

nose 还有一些选项,可以自动显示在断言中提到的变量,或者在测试失败时调用调试器。例如,-s (--nocapture) 这个选项可以防止捕获标准输出。

84

在Python 2.7中,你可以使用一个额外的参数,msg,来给错误信息添加一些说明,像这样:

self.assertEqual(f.bar(t2), 2, msg='{0}, {1}'.format(t1, t2))

官方文档可以在这里找到。

85

我们使用日志模块来实现这个功能。

比如说:

import logging
class SomeTest( unittest.TestCase ):
    def testSomething( self ):
        log= logging.getLogger( "SomeTest.testSomething" )
        log.debug( "this= %r", self.this )
        log.debug( "that= %r", self.that )
        self.assertEqual( 3.14, pi )

if __name__ == "__main__":
    logging.basicConfig( stream=sys.stderr )
    logging.getLogger( "SomeTest.testSomething" ).setLevel( logging.DEBUG )
    unittest.main()

这样我们就可以为一些特定的测试打开调试功能,这些测试我们知道是失败的,并且我们想要更多的调试信息来帮助我们找出问题。

不过,我更喜欢的方法不是花很多时间在调试上,而是花时间写更详细的测试,以便更好地发现问题。

撰写回答