Source From Here
Question
I have a very large TestSuite that I run with TextTestRunner from the python unittest framework. Unfortunately I have no idea how many tests are already done while the test are running.
Basically I'd like to convert this output:
to
Do I have to subclass
TextTestRunner to achieve this and if yes, how?
How-To
Here's one way that you could subclass TextTestRunner and TextTestResult to achieve the desired result:
- demo_unittest.py
Execution result:
Question
I have a very large TestSuite that I run with TextTestRunner from the python unittest framework. Unfortunately I have no idea how many tests are already done while the test are running.
Basically I'd like to convert this output:
- test_choice (__main__.TestSequenceFunctions) ... ok
- test_sample (__main__.TestSequenceFunctions) ... ok
- test_shuffle (__main__.TestSequenceFunctions) ... ok
- ----------------------------------------------------------------------
- Ran 3 tests in 0.110s
- OK
- [1/3] test_choice (__main__.TestSequenceFunctions) ... ok
- [2/3] test_sample (__main__.TestSequenceFunctions) ... ok
- [3/3] test_shuffle (__main__.TestSequenceFunctions) ... ok
- ----------------------------------------------------------------------
- Ran 3 tests in 0.110s
- OK
How-To
Here's one way that you could subclass TextTestRunner and TextTestResult to achieve the desired result:
- demo_unittest.py
- #!/usr/bin/env python
- import unittest
- import unittest.runner
- import itertools
- import collections
- class CustomTextTestResult(unittest.runner.TextTestResult):
- """Extension of TextTestResult to support numbering test cases"""
- def __init__(self, stream, descriptions, verbosity):
- """Initializes the test number generator, then calls super impl"""
- self.test_numbers = itertools.count(1)
- return super(CustomTextTestResult, self).__init__(stream, descriptions, verbosity)
- def startTest(self, test):
- """Writes the test number to the stream if showAll is set, then calls super impl"""
- if self.showAll:
- progress = '[{0}/{1}] '.format(next(self.test_numbers), self.test_case_count)
- self.stream.write(progress)
- # Also store the progress in the test itself, so that if it errors,
- # it can be written to the exception information by our overridden
- # _exec_info_to_string method:
- test.progress_index = progress
- return super(CustomTextTestResult, self).startTest(test)
- def _exc_info_to_string(self, err, test):
- """Gets an exception info string from super, and prepends 'Test Number' line"""
- info = super(CustomTextTestResult, self)._exc_info_to_string(err, test)
- if self.showAll:
- info = 'Test number: {index}\n{info}'.format(
- index=test.progress_index,
- info=info
- )
- return info
- class CustomTextTestRunner(unittest.runner.TextTestRunner):
- """Extension of TextTestRunner to support numbering test cases"""
- resultclass = CustomTextTestResult
- def run(self, test):
- """Stores the total count of test cases, then calls super impl"""
- self.test_case_count = test.countTestCases()
- return super(CustomTextTestRunner, self).run(test)
- def _makeResult(self):
- """Creates and returns a result instance that knows the count of test cases"""
- result = super(CustomTextTestRunner, self)._makeResult()
- result.test_case_count = self.test_case_count
- return result
- class TestSequenceFunctions(unittest.TestCase):
- """Dummy test case to illustrate usage"""
- fail_1 = 0
- fail_2 = 0
- def test_choice(self):
- pass
- def test_sample(self):
- self.fail_1 += 1
- if self.fail_1 == 2:
- raise Exception()
- def test_shuffle(self):
- self.fail_2 += 1
- if self.fail_2 == 3:
- raise Exception()
- def get_tests():
- test_funcs = ['test_choice', 'test_sample', 'test_shuffle']
- return [TestSequenceFunctions(func) for func in test_funcs]
- if __name__ == '__main__':
- test_suite = unittest.TestSuite()
- repetitions = 3
- tests = get_tests()
- for __ in xrange(0, repetitions):
- test_suite.addTests(tests)
- CustomTextTestRunner(verbosity=2).run(test_suite)
沒有留言:
張貼留言