简体   繁体   中英

Python unittest - how can I add debugging information to a TestResult object?

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

You just need to use TextTestRunner buffer option:

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)

Before each test, TextTestResult , used by the runner, will replace sys.stderr and sys.stdout with its own streams and only send the content to the original streams if the test fails or discards it otherwise.

Note that because the fake sys.std* streams changes after each test, if you wanted to to do the same thing with logging output, you would have to add the logging handler after the sys.sdt* stream have been replaced, before each test or implement your own handler.

Here's an example subclassing 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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM