2

I have some unittest code that runs a bunch of tests. Previously, when each test was run some information would get printed to stdout. This information would greatly assist in debugging in case the test failed. Now I would like to to write a more sophisticated program that invokes unittest and captures the results of the testing programmatically. It appears that unittest provides an object called TestResult which is meant to contain the output of tests. It has a list of all the errors, a list of all the failures, etc. I would also like to add my debugging output to this object so that I can access it programmatically later. Is this possible?

EDIT: Here is an example:

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
4

1 回答 1

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)
于 2013-12-02T02:10:33.037 回答