Python unittest - 如何将调试信息添加到TestResult对象?

时间:2013-01-09 18:58:46

标签: python unit-testing

我有一些运行一系列测试的unittest代码。以前,当每个测试运行时,一些信息将打印到stdout。如果测试失败,此信息将极大地帮助调试。现在我想编写一个更复杂的程序来调用unittest并以编程方式捕获测试结果。看来unittest提供了一个名为TestResult的对象,它意味着包含测试的输出。它有一个所有错误的列表,所有失败的列表等。我还想将我的调试输出添加到这个对象,以便我可以稍后以编程方式访问它。这可能吗?

编辑:这是一个例子:

import unittest2

class DemoTest(unittest2.TestCase):
    def test_one(self):
        print "'grimelsome' attribute of 'smoxy' was set to 'blimpy'"
        self.assertTrue(True)

    def test_two(self):
        print "'smithereen' attribute of 'brouhaha' was set to 'False'"
        self.assertTrue(True)

if __name__ == '__main__':
    suite = unittest2.TestLoader().loadTestsFromTestCase(DemoTest)
    result = unittest2.TextTestRunner(verbosity=2).run(suite)

    # this is what I'd like to be able to do:
    for fail in result.failures:
        print what_would_have_gone_to_stdout

1 个答案:

答案 0 :(得分:0)

您只需要使用TextTestRunner缓冲区选项:

import unittest2

class DemoTest(unittest2.TestCase):
    def test_one(self):
        print "'grimelsome' attribute of 'smoxy' was set to 'blimpy'"
        self.assertTrue(True)

    def test_two(self):
        print "'smithereen' attribute of 'brouhaha' was set to 'False'"
        self.assertTrue(False)

if __name__ == '__main__':
    suite = unittest2.TestLoader().loadTestsFromTestCase(DemoTest)
    result = unittest2.TextTestRunner(verbosity=2, buffer=True).run(suite)

在每次测试之前,由跑步者使用的TextTestResult将使用自己的流替换sys.stderrsys.stdout,并且只有在测试失败或丢弃时才将内容发送到原始流否则。

请注意,因为假的sys.std*流在每次测试后都会发生变化,如果您想对日志输出执行相同的操作,则必须在更换sys.sdt *流后添加日志记录处理程序,在每次测试之前或实现自己的处理程序。

这是一个子类化logging.StreamHandler的示例:

import logging
import sys
import unittest2


class DemoTest(unittest2.TestCase):
    logger = logging.getLogger('DemoTest')

    def setUp(self):
        self.logger.debug("setting up stuff and logging it...")

    def teardown(self):
        self.logger.debug("You won't see me")
        print "me neither"

    def test_one(self):
        self.logger.debug("'grimelsome' attribute of 'smoxy' was set to 'blimpy'")
        self.assertTrue(True)

    def test_two(self):
        self.logger.debug("'smithereen' attribute of 'brouhaha' was set to 'False'")
        self.assertTrue(False)


class TestHandler(logging.StreamHandler):

    def __init__(self):
        logging.Handler.__init__(self)

    @property
    def stream(self):
        """Use which ever stream sys.stderr is referencing."""
        return sys.stderr


if __name__ == '__main__':
    formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
    logger_handler = TestHandler()
    logger_handler.setFormatter(formatter)
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    logger.addHandler(logger_handler)

    suite = unittest2.TestLoader().loadTestsFromTestCase(DemoTest)
    result = unittest2.TextTestRunner(
        verbosity=2, buffer=True, resultclass=TestResult
    ).run(suite)