_asyncrunner.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. # -*- test-case-name: twisted.trial.test -*-
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. """
  5. Infrastructure for test running and suites.
  6. """
  7. from __future__ import division, absolute_import
  8. import doctest
  9. import gc
  10. from twisted.python import components
  11. from twisted.trial import itrial, reporter
  12. from twisted.trial._synctest import _logObserver
  13. pyunit = __import__('unittest')
  14. from zope.interface import implementer
  15. class TestSuite(pyunit.TestSuite):
  16. """
  17. Extend the standard library's C{TestSuite} with a consistently overrideable
  18. C{run} method.
  19. """
  20. def run(self, result):
  21. """
  22. Call C{run} on every member of the suite.
  23. """
  24. for test in self._tests:
  25. if result.shouldStop:
  26. break
  27. test(result)
  28. return result
  29. @implementer(itrial.ITestCase)
  30. class TestDecorator(components.proxyForInterface(itrial.ITestCase,
  31. "_originalTest")):
  32. """
  33. Decorator for test cases.
  34. @param _originalTest: The wrapped instance of test.
  35. @type _originalTest: A provider of L{itrial.ITestCase}
  36. """
  37. def __call__(self, result):
  38. """
  39. Run the unit test.
  40. @param result: A TestResult object.
  41. """
  42. return self.run(result)
  43. def run(self, result):
  44. """
  45. Run the unit test.
  46. @param result: A TestResult object.
  47. """
  48. return self._originalTest.run(
  49. reporter._AdaptedReporter(result, self.__class__))
  50. def _clearSuite(suite):
  51. """
  52. Clear all tests from C{suite}.
  53. This messes with the internals of C{suite}. In particular, it assumes that
  54. the suite keeps all of its tests in a list in an instance variable called
  55. C{_tests}.
  56. """
  57. suite._tests = []
  58. def decorate(test, decorator):
  59. """
  60. Decorate all test cases in C{test} with C{decorator}.
  61. C{test} can be a test case or a test suite. If it is a test suite, then the
  62. structure of the suite is preserved.
  63. L{decorate} tries to preserve the class of the test suites it finds, but
  64. assumes the presence of the C{_tests} attribute on the suite.
  65. @param test: The C{TestCase} or C{TestSuite} to decorate.
  66. @param decorator: A unary callable used to decorate C{TestCase}s.
  67. @return: A decorated C{TestCase} or a C{TestSuite} containing decorated
  68. C{TestCase}s.
  69. """
  70. try:
  71. tests = iter(test)
  72. except TypeError:
  73. return decorator(test)
  74. # At this point, we know that 'test' is a test suite.
  75. _clearSuite(test)
  76. for case in tests:
  77. test.addTest(decorate(case, decorator))
  78. return test
  79. class _PyUnitTestCaseAdapter(TestDecorator):
  80. """
  81. Adapt from pyunit.TestCase to ITestCase.
  82. """
  83. class _BrokenIDTestCaseAdapter(_PyUnitTestCaseAdapter):
  84. """
  85. Adapter for pyunit-style C{TestCase} subclasses that have undesirable id()
  86. methods. That is C{unittest.FunctionTestCase} and C{unittest.DocTestCase}.
  87. """
  88. def id(self):
  89. """
  90. Return the fully-qualified Python name of the doctest.
  91. """
  92. testID = self._originalTest.shortDescription()
  93. if testID is not None:
  94. return testID
  95. return self._originalTest.id()
  96. class _ForceGarbageCollectionDecorator(TestDecorator):
  97. """
  98. Forces garbage collection to be run before and after the test. Any errors
  99. logged during the post-test collection are added to the test result as
  100. errors.
  101. """
  102. def run(self, result):
  103. gc.collect()
  104. TestDecorator.run(self, result)
  105. _logObserver._add()
  106. gc.collect()
  107. for error in _logObserver.getErrors():
  108. result.addError(self, error)
  109. _logObserver.flushErrors()
  110. _logObserver._remove()
  111. components.registerAdapter(
  112. _PyUnitTestCaseAdapter, pyunit.TestCase, itrial.ITestCase)
  113. components.registerAdapter(
  114. _BrokenIDTestCaseAdapter, pyunit.FunctionTestCase, itrial.ITestCase)
  115. _docTestCase = getattr(doctest, 'DocTestCase', None)
  116. if _docTestCase:
  117. components.registerAdapter(
  118. _BrokenIDTestCaseAdapter, _docTestCase, itrial.ITestCase)
  119. def _iterateTests(testSuiteOrCase):
  120. """
  121. Iterate through all of the test cases in C{testSuiteOrCase}.
  122. """
  123. try:
  124. suite = iter(testSuiteOrCase)
  125. except TypeError:
  126. yield testSuiteOrCase
  127. else:
  128. for test in suite:
  129. for subtest in _iterateTests(test):
  130. yield subtest