diff options
author | Benjamin Peterson <benjamin@python.org> | 2009-05-08 20:42:26 (GMT) |
---|---|---|
committer | Benjamin Peterson <benjamin@python.org> | 2009-05-08 20:42:26 (GMT) |
commit | 25c95f12987c08f446f355db6b9a807f3dea76a0 (patch) | |
tree | 9d70b6e22b45cec0e40cc6d5d174d03012af7f50 /Lib/unittest.py | |
parent | 8a282d175b5a9f1cd48c5de506fb02d60b20d6d5 (diff) | |
download | cpython-25c95f12987c08f446f355db6b9a807f3dea76a0.zip cpython-25c95f12987c08f446f355db6b9a807f3dea76a0.tar.gz cpython-25c95f12987c08f446f355db6b9a807f3dea76a0.tar.bz2 |
Merged revisions 70768,71657,71721,71729,71794,71976,72036-72037,72079,72085,72131-72134,72191,72197-72198,72219,72221,72225,72303,72434,72467,72476 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r70768 | andrew.kuchling | 2009-03-30 17:29:15 -0500 (Mon, 30 Mar 2009) | 1 line
Typo fixes
........
r71657 | vinay.sajip | 2009-04-16 14:07:37 -0500 (Thu, 16 Apr 2009) | 1 line
Issue #5768: Change to Unicode output logic and test case for same.
........
r71721 | benjamin.peterson | 2009-04-18 14:26:19 -0500 (Sat, 18 Apr 2009) | 1 line
fix a few nits in unittest.py #5771
........
r71729 | benjamin.peterson | 2009-04-18 16:03:10 -0500 (Sat, 18 Apr 2009) | 1 line
move test to a more appropiate one
........
r71794 | vinay.sajip | 2009-04-22 07:10:47 -0500 (Wed, 22 Apr 2009) | 2 lines
Issue #5170: Fixed regression caused when fixing #5768.
........
r71976 | mark.dickinson | 2009-04-26 14:54:55 -0500 (Sun, 26 Apr 2009) | 2 lines
Fix typo in function name
........
r72036 | georg.brandl | 2009-04-27 12:04:23 -0500 (Mon, 27 Apr 2009) | 1 line
#5848: small unittest doc patch.
........
r72037 | georg.brandl | 2009-04-27 12:09:53 -0500 (Mon, 27 Apr 2009) | 1 line
#5840: dont claim we dont support TLS.
........
r72079 | r.david.murray | 2009-04-28 14:02:55 -0500 (Tue, 28 Apr 2009) | 2 lines
Remove spurious 'u'.
........
r72085 | georg.brandl | 2009-04-28 16:48:35 -0500 (Tue, 28 Apr 2009) | 1 line
Make the doctests in the docs pass, except for those in the turtle module.
........
r72131 | benjamin.peterson | 2009-04-29 17:43:35 -0500 (Wed, 29 Apr 2009) | 1 line
fix test_shutil on ZFS #5676
........
r72132 | georg.brandl | 2009-04-29 17:44:07 -0500 (Wed, 29 Apr 2009) | 1 line
#5878: fix repr of re object.
........
r72133 | benjamin.peterson | 2009-04-29 17:44:15 -0500 (Wed, 29 Apr 2009) | 1 line
make sure mode is removable while cleaning up test droppings
........
r72134 | benjamin.peterson | 2009-04-29 19:06:33 -0500 (Wed, 29 Apr 2009) | 1 line
make sure to close file
........
r72191 | michael.foord | 2009-05-02 06:43:06 -0500 (Sat, 02 May 2009) | 9 lines
Adds an exit parameter to unittest.main(). If False main no longer
calls sys.exit.
Closes issue 3379.
Michael Foord
........
r72197 | benjamin.peterson | 2009-05-02 11:24:37 -0500 (Sat, 02 May 2009) | 1 line
don't let sys.argv be used in the tests
........
r72198 | andrew.kuchling | 2009-05-02 12:12:15 -0500 (Sat, 02 May 2009) | 1 line
Add items
........
r72219 | michael.foord | 2009-05-02 15:15:05 -0500 (Sat, 02 May 2009) | 8 lines
Add addCleanup and doCleanups to unittest.TestCase.
Closes issue 5679.
Michael Foord
........
r72221 | benjamin.peterson | 2009-05-02 15:26:53 -0500 (Sat, 02 May 2009) | 1 line
add myself
........
r72225 | michael.foord | 2009-05-02 17:43:34 -0500 (Sat, 02 May 2009) | 1 line
........
r72303 | benjamin.peterson | 2009-05-04 19:55:24 -0500 (Mon, 04 May 2009) | 1 line
using sys._getframe(x), where x > 0 doesnt' work on IronPython
........
r72434 | r.david.murray | 2009-05-07 13:09:58 -0500 (Thu, 07 May 2009) | 2 lines
Pre-opened test file needs to be opened in binary mode.
........
r72467 | georg.brandl | 2009-05-08 07:17:34 -0500 (Fri, 08 May 2009) | 1 line
Fix name.
........
r72476 | thomas.heller | 2009-05-08 15:09:40 -0500 (Fri, 08 May 2009) | 4 lines
Add a file that contains diffs between offical libffi files and the
files in this repository. Should make it easier to merge new libffi
versions.
........
Diffstat (limited to 'Lib/unittest.py')
-rw-r--r-- | Lib/unittest.py | 117 |
1 files changed, 87 insertions, 30 deletions
diff --git a/Lib/unittest.py b/Lib/unittest.py index 0b7cea4..c6d893e 100644 --- a/Lib/unittest.py +++ b/Lib/unittest.py @@ -173,10 +173,22 @@ class TestResult(object): "Called when the given test is about to be run" self.testsRun = self.testsRun + 1 + def startTestRun(self): + """Called once before any tests are executed. + + See startTest for a method called before each test. + """ + def stopTest(self, test): "Called when the given test has been run" pass + def stopTestRun(self): + """Called once after all tests are executed. + + See stopTest for a method called after each test. + """ + def addError(self, test, err): """Called when an error has occurred. 'err' is a tuple of values as returned by sys.exc_info(). @@ -262,7 +274,7 @@ class _AssertRaisesContext(object): def __enter__(self): pass - def __exit__(self, exc_type, exc_value, traceback): + def __exit__(self, exc_type, exc_value, tb): if exc_type is None: try: exc_name = self.expected.__name__ @@ -341,12 +353,14 @@ class TestCase(object): not have a method with the specified name. """ self._testMethodName = methodName + self._result = None try: testMethod = getattr(self, methodName) except AttributeError: raise ValueError("no such test method in %s: %s" % \ (self.__class__, methodName)) self._testMethodDoc = testMethod.__doc__ + self._cleanups = [] # Map types to custom assertEqual functions that will compare # instances of said type in more detail to generate a more useful @@ -373,6 +387,14 @@ class TestCase(object): """ self._type_equality_funcs[typeobj] = _AssertWrapper(function) + def addCleanup(self, function, *args, **kwargs): + """Add a function, with arguments, to be called when the test is + completed. Functions added are called on a LIFO basis and are + called after tearDown on test failure or success. + + Cleanup items are called even if setUp fails (unlike tearDown).""" + self._cleanups.append((function, args, kwargs)) + def setUp(self): "Hook method for setting up the test fixture before exercising it." pass @@ -428,45 +450,70 @@ class TestCase(object): (_strclass(self.__class__), self._testMethodName) def run(self, result=None): + orig_result = result if result is None: result = self.defaultTestResult() + startTestRun = getattr(result, 'startTestRun', None) + if startTestRun is not None: + startTestRun() + + self._result = result result.startTest(self) testMethod = getattr(self, self._testMethodName) try: - try: - self.setUp() - except SkipTest as e: - result.addSkip(self, str(e)) - return - except Exception: - result.addError(self, sys.exc_info()) - return - success = False try: - testMethod() - except self.failureException: - result.addFailure(self, sys.exc_info()) - except _ExpectedFailure as e: - result.addExpectedFailure(self, e.exc_info) - except _UnexpectedSuccess: - result.addUnexpectedSuccess(self) + self.setUp() except SkipTest as e: result.addSkip(self, str(e)) except Exception: result.addError(self, sys.exc_info()) else: - success = True + try: + testMethod() + except self.failureException: + result.addFailure(self, sys.exc_info()) + except _ExpectedFailure as e: + result.addExpectedFailure(self, e.exc_info) + except _UnexpectedSuccess: + result.addUnexpectedSuccess(self) + except SkipTest as e: + result.addSkip(self, str(e)) + except Exception: + result.addError(self, sys.exc_info()) + else: + success = True - try: - self.tearDown() - except Exception: - result.addError(self, sys.exc_info()) - success = False + try: + self.tearDown() + except Exception: + result.addError(self, sys.exc_info()) + success = False + + cleanUpSuccess = self.doCleanups() + success = success and cleanUpSuccess if success: result.addSuccess(self) finally: result.stopTest(self) + if orig_result is None: + stopTestRun = getattr(result, 'stopTestRun', None) + if stopTestRun is not None: + stopTestRun() + + def doCleanups(self): + """Execute all cleanup functions. Normally called for you after + tearDown.""" + result = self._result + ok = True + while self._cleanups: + function, args, kwargs = self._cleanups.pop(-1) + try: + function(*args, **kwargs) + except Exception: + ok = False + result.addError(self, sys.exc_info()) + return ok def __call__(self, *args, **kwds): return self.run(*args, **kwds) @@ -1037,7 +1084,7 @@ class TestSuite(object): def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return self._tests == other._tests + return list(self) == list(other) def __ne__(self, other): return not self == other @@ -1160,8 +1207,7 @@ class FunctionTestCase(TestCase): self._testFunc, self._description)) def __str__(self): - return "%s (%s)" % (_strclass(self.__class__), - self.__testFunc.__name__) + return "%s (%s)" % (_strclass(self.__class__), self._testFunc.__name__) def __repr__(self): return "<%s testFunc=%s>" % (_strclass(self.__class__), self._testFunc) @@ -1449,7 +1495,15 @@ class TextTestRunner(object): "Run the given test case or test suite." result = self._makeResult() startTime = time.time() - test(result) + startTestRun = getattr(result, 'startTestRun', None) + if startTestRun is not None: + startTestRun() + try: + test(result) + finally: + stopTestRun = getattr(result, 'stopTestRun', None) + if stopTestRun is not None: + stopTestRun() stopTime = time.time() timeTaken = stopTime - startTime result.printErrors() @@ -1511,7 +1565,7 @@ Examples: """ def __init__(self, module='__main__', defaultTest=None, argv=None, testRunner=TextTestRunner, - testLoader=defaultTestLoader): + testLoader=defaultTestLoader, exit=True): if isinstance(module, str): self.module = __import__(module) for part in module.split('.')[1:]: @@ -1520,6 +1574,8 @@ Examples: self.module = module if argv is None: argv = sys.argv + + self.exit = exit self.verbosity = 1 self.defaultTest = defaultTest self.testRunner = testRunner @@ -1571,8 +1627,9 @@ Examples: else: # it is assumed to be a TestRunner instance testRunner = self.testRunner - result = testRunner.run(self.test) - sys.exit(not result.wasSuccessful()) + self.result = testRunner.run(self.test) + if self.exit: + sys.exit(not self.result.wasSuccessful()) main = TestProgram |