Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

_asyncrunner.py 4.5KB

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