Viewing file: _asyncrunner.py (4.42 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
# -*- test-case-name: twisted.trial.test -*- # Copyright (c) Twisted Matrix Laboratories. # See LICENSE for details.
""" Infrastructure for test running and suites. """
from __future__ import division, absolute_import
import doctest import gc
from twisted.python import components
from twisted.trial import itrial, reporter from twisted.trial._synctest import _logObserver
pyunit = __import__('unittest')
from zope.interface import implementer
class TestSuite(pyunit.TestSuite): """ Extend the standard library's C{TestSuite} with a consistently overrideable C{run} method. """
def run(self, result): """ Call C{run} on every member of the suite. """ for test in self._tests: if result.shouldStop: break test(result) return result
@implementer(itrial.ITestCase) class TestDecorator(components.proxyForInterface(itrial.ITestCase, "_originalTest")): """ Decorator for test cases.
@param _originalTest: The wrapped instance of test. @type _originalTest: A provider of L{itrial.ITestCase} """
def __call__(self, result): """ Run the unit test.
@param result: A TestResult object. """ return self.run(result)
def run(self, result): """ Run the unit test.
@param result: A TestResult object. """ return self._originalTest.run( reporter._AdaptedReporter(result, self.__class__))
def _clearSuite(suite): """ Clear all tests from C{suite}.
This messes with the internals of C{suite}. In particular, it assumes that the suite keeps all of its tests in a list in an instance variable called C{_tests}. """ suite._tests = []
def decorate(test, decorator): """ Decorate all test cases in C{test} with C{decorator}.
C{test} can be a test case or a test suite. If it is a test suite, then the structure of the suite is preserved.
L{decorate} tries to preserve the class of the test suites it finds, but assumes the presence of the C{_tests} attribute on the suite.
@param test: The C{TestCase} or C{TestSuite} to decorate.
@param decorator: A unary callable used to decorate C{TestCase}s.
@return: A decorated C{TestCase} or a C{TestSuite} containing decorated C{TestCase}s. """
try: tests = iter(test) except TypeError: return decorator(test)
# At this point, we know that 'test' is a test suite. _clearSuite(test)
for case in tests: test.addTest(decorate(case, decorator)) return test
class _PyUnitTestCaseAdapter(TestDecorator): """ Adapt from pyunit.TestCase to ITestCase. """
class _BrokenIDTestCaseAdapter(_PyUnitTestCaseAdapter): """ Adapter for pyunit-style C{TestCase} subclasses that have undesirable id() methods. That is C{unittest.FunctionTestCase} and C{unittest.DocTestCase}. """
def id(self): """ Return the fully-qualified Python name of the doctest. """ testID = self._originalTest.shortDescription() if testID is not None: return testID return self._originalTest.id()
class _ForceGarbageCollectionDecorator(TestDecorator): """ Forces garbage collection to be run before and after the test. Any errors logged during the post-test collection are added to the test result as errors. """
def run(self, result): gc.collect() TestDecorator.run(self, result) _logObserver._add() gc.collect() for error in _logObserver.getErrors(): result.addError(self, error) _logObserver.flushErrors() _logObserver._remove()
components.registerAdapter( _PyUnitTestCaseAdapter, pyunit.TestCase, itrial.ITestCase)
components.registerAdapter( _BrokenIDTestCaseAdapter, pyunit.FunctionTestCase, itrial.ITestCase)
_docTestCase = getattr(doctest, 'DocTestCase', None) if _docTestCase: components.registerAdapter( _BrokenIDTestCaseAdapter, _docTestCase, itrial.ITestCase)
def _iterateTests(testSuiteOrCase): """ Iterate through all of the test cases in C{testSuiteOrCase}. """ try: suite = iter(testSuiteOrCase) except TypeError: yield testSuiteOrCase else: for test in suite: for subtest in _iterateTests(test): yield subtest
|