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/test | |
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/test')
-rwxr-xr-x | Lib/test/regrtest.py | 5 | ||||
-rw-r--r-- | Lib/test/test_aifc.py | 2 | ||||
-rw-r--r-- | Lib/test/test_descr.py | 55 | ||||
-rw-r--r-- | Lib/test/test_logging.py | 1 | ||||
-rw-r--r-- | Lib/test/test_shutil.py | 18 | ||||
-rw-r--r-- | Lib/test/test_unittest.py | 413 |
6 files changed, 427 insertions, 67 deletions
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py index 0408a02..673f11f 100755 --- a/Lib/test/regrtest.py +++ b/Lib/test/regrtest.py @@ -663,6 +663,7 @@ def runtest_inner(test, generate, verbose, quiet, test_times, def cleanup_test_droppings(testname, verbose): import shutil + import stat # Try to clean up junk commonly left behind. While tests shouldn't leave # any files or directories behind, when a test fails that can be tedious @@ -687,6 +688,10 @@ def cleanup_test_droppings(testname, verbose): if verbose: print("%r left behind %s %r" % (testname, kind, name)) try: + # if we have chmod, fix possible permissions problems + # that might prevent cleanup + if (hasattr(os, 'chmod')): + os.chmod(name, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) nuker(name) except Exception as msg: print(("%r left behind %s %r and it couldn't be " diff --git a/Lib/test/test_aifc.py b/Lib/test/test_aifc.py index 0248615..4869bf3 100644 --- a/Lib/test/test_aifc.py +++ b/Lib/test/test_aifc.py @@ -27,7 +27,7 @@ class AIFCTest(unittest.TestCase): def test_skipunknown(self): #Issue 2245 #This file contains chunk types aifc doesn't recognize. - f = aifc.open(self.sndfilepath) + self.f = aifc.open(self.sndfilepath) def test_params(self): f = self.f = aifc.open(self.sndfilepath) diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py index ba0e0b8..37cab01 100644 --- a/Lib/test/test_descr.py +++ b/Lib/test/test_descr.py @@ -3585,31 +3585,6 @@ order (MRO) for bases """ self.assertEqual(e.a, 2) self.assertEqual(C2.__subclasses__(), [D]) - # stuff that shouldn't: - class L(list): - pass - - try: - L.__bases__ = (dict,) - except TypeError: - pass - else: - self.fail("shouldn't turn list subclass into dict subclass") - - try: - list.__bases__ = (dict,) - except TypeError: - pass - else: - self.fail("shouldn't be able to assign to list.__bases__") - - try: - D.__bases__ = (C2, list) - except TypeError: - pass - else: - assert 0, "best_base calculation found wanting" - try: del D.__bases__ except (TypeError, AttributeError): @@ -3657,6 +3632,36 @@ order (MRO) for bases """ if tp is not object: self.assertEqual(len(tp.__bases__), 1, tp) + class L(list): + pass + + class C(object): + pass + + class D(C): + pass + + try: + L.__bases__ = (dict,) + except TypeError: + pass + else: + self.fail("shouldn't turn list subclass into dict subclass") + + try: + list.__bases__ = (dict,) + except TypeError: + pass + else: + self.fail("shouldn't be able to assign to list.__bases__") + + try: + D.__bases__ = (C, list) + except TypeError: + pass + else: + assert 0, "best_base calculation found wanting" + def test_mutable_bases_with_failing_mro(self): # Testing mutable bases with failing mro... diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py index 1463cf7..69ec491 100644 --- a/Lib/test/test_logging.py +++ b/Lib/test/test_logging.py @@ -894,6 +894,7 @@ class EncodingTest(BaseTest): message = '\u0434\u043e \u0441\u0432\u0438\u0434\u0430\u043d\u0438\u044f' #Ensure it's written in a Cyrillic encoding writer_class = codecs.getwriter('cp1251') + writer_class.encoding = 'cp1251' stream = io.BytesIO() writer = writer_class(stream, 'strict') handler = logging.StreamHandler(writer) diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index cdb039d..5a546ec 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -46,9 +46,23 @@ class TestShutil(unittest.TestCase): shutil.rmtree(TESTFN) def check_args_to_onerror(self, func, arg, exc): + # test_rmtree_errors deliberately runs rmtree + # on a directory that is chmod 400, which will fail. + # This function is run when shutil.rmtree fails. + # 99.9% of the time it initially fails to remove + # a file in the directory, so the first time through + # func is os.remove. + # However, some Linux machines running ZFS on + # FUSE experienced a failure earlier in the process + # at os.listdir. The first failure may legally + # be either. if self.errorState == 0: - self.assertEqual(func, os.remove) - self.assertEqual(arg, self.childpath) + if func is os.remove: + self.assertEqual(arg, self.childpath) + else: + self.assertIs(func, os.listdir, + "func must be either os.remove or os.listdir") + self.assertEqual(arg, TESTFN) self.failUnless(issubclass(exc[0], OSError)) self.errorState = 1 else: diff --git a/Lib/test/test_unittest.py b/Lib/test/test_unittest.py index d0d2049..e7097cc 100644 --- a/Lib/test/test_unittest.py +++ b/Lib/test/test_unittest.py @@ -9,9 +9,10 @@ Still need testing: import re from test import support import unittest -from unittest import TestCase +from unittest import TestCase, TestProgram import types from copy import deepcopy +import io ### Support code ################################################################ @@ -25,10 +26,18 @@ class LoggingResult(unittest.TestResult): self._events.append('startTest') super().startTest(test) + def startTestRun(self): + self._events.append('startTestRun') + super(LoggingResult, self).startTestRun() + def stopTest(self, test): self._events.append('stopTest') super().stopTest(test) + def stopTestRun(self): + self._events.append('stopTestRun') + super(LoggingResult, self).stopTestRun() + def addFailure(self, *args): self._events.append('addFailure') super().addFailure(*args) @@ -1826,6 +1835,12 @@ class Test_TestResult(TestCase): self.assertEqual(result.testsRun, 1) self.assertEqual(result.shouldStop, False) + # "Called before and after tests are run. The default implementation does nothing." + def test_startTestRun_stopTestRun(self): + result = unittest.TestResult() + result.startTestRun() + result.stopTestRun() + # "addSuccess(test)" # ... # "Called when the test case test succeeds" @@ -1973,6 +1988,53 @@ class Foo(unittest.TestCase): class Bar(Foo): def test2(self): pass +class LoggingTestCase(unittest.TestCase): + """A test case which logs its calls.""" + + def __init__(self, events): + super(LoggingTestCase, self).__init__('test') + self.events = events + + def setUp(self): + self.events.append('setUp') + + def test(self): + self.events.append('test') + + def tearDown(self): + self.events.append('tearDown') + +class ResultWithNoStartTestRunStopTestRun(object): + """An object honouring TestResult before startTestRun/stopTestRun.""" + + def __init__(self): + self.failures = [] + self.errors = [] + self.testsRun = 0 + self.skipped = [] + self.expectedFailures = [] + self.unexpectedSuccesses = [] + self.shouldStop = False + + def startTest(self, test): + pass + + def stopTest(self, test): + pass + + def addError(self, test): + pass + + def addFailure(self, test): + pass + + def addSuccess(self, test): + pass + + def wasSuccessful(self): + return True + + ################################################################ ### /Support code for Test_TestCase @@ -2067,19 +2129,30 @@ class Test_TestCase(TestCase, TestEquality, TestHashing): events = [] result = LoggingResult(events) - class Foo(unittest.TestCase): + class Foo(LoggingTestCase): def setUp(self): - events.append('setUp') + super(Foo, self).setUp() raise RuntimeError('raised by Foo.setUp') - def test(self): - events.append('test') + Foo(events).run(result) + expected = ['startTest', 'setUp', 'addError', 'stopTest'] + self.assertEqual(events, expected) - def tearDown(self): - events.append('tearDown') + # "With a temporary result stopTestRun is called when setUp errors. + def test_run_call_order__error_in_setUp_default_result(self): + events = [] - Foo('test').run(result) - expected = ['startTest', 'setUp', 'addError', 'stopTest'] + class Foo(LoggingTestCase): + def defaultTestResult(self): + return LoggingResult(self.events) + + def setUp(self): + super(Foo, self).setUp() + raise RuntimeError('raised by Foo.setUp') + + Foo(events).run() + expected = ['startTestRun', 'startTest', 'setUp', 'addError', + 'stopTest', 'stopTestRun'] self.assertEqual(events, expected) # "When a setUp() method is defined, the test runner will run that method @@ -2093,20 +2166,32 @@ class Test_TestCase(TestCase, TestEquality, TestHashing): events = [] result = LoggingResult(events) - class Foo(unittest.TestCase): - def setUp(self): - events.append('setUp') - + class Foo(LoggingTestCase): def test(self): - events.append('test') + super(Foo, self).test() raise RuntimeError('raised by Foo.test') - def tearDown(self): - events.append('tearDown') - expected = ['startTest', 'setUp', 'test', 'addError', 'tearDown', 'stopTest'] - Foo('test').run(result) + Foo(events).run(result) + self.assertEqual(events, expected) + + # "With a default result, an error in the test still results in stopTestRun + # being called." + def test_run_call_order__error_in_test_default_result(self): + events = [] + + class Foo(LoggingTestCase): + def defaultTestResult(self): + return LoggingResult(self.events) + + def test(self): + super(Foo, self).test() + raise RuntimeError('raised by Foo.test') + + expected = ['startTestRun', 'startTest', 'setUp', 'test', 'addError', + 'tearDown', 'stopTest', 'stopTestRun'] + Foo(events).run() self.assertEqual(events, expected) # "When a setUp() method is defined, the test runner will run that method @@ -2120,20 +2205,30 @@ class Test_TestCase(TestCase, TestEquality, TestHashing): events = [] result = LoggingResult(events) - class Foo(unittest.TestCase): - def setUp(self): - events.append('setUp') - + class Foo(LoggingTestCase): def test(self): - events.append('test') + super(Foo, self).test() self.fail('raised by Foo.test') - def tearDown(self): - events.append('tearDown') - expected = ['startTest', 'setUp', 'test', 'addFailure', 'tearDown', 'stopTest'] - Foo('test').run(result) + Foo(events).run(result) + self.assertEqual(events, expected) + + # "When a test fails with a default result stopTestRun is still called." + def test_run_call_order__failure_in_test_default_result(self): + + class Foo(LoggingTestCase): + def defaultTestResult(self): + return LoggingResult(self.events) + def test(self): + super(Foo, self).test() + self.fail('raised by Foo.test') + + expected = ['startTestRun', 'startTest', 'setUp', 'test', 'addFailure', + 'tearDown', 'stopTest', 'stopTestRun'] + events = [] + Foo(events).run() self.assertEqual(events, expected) # "When a setUp() method is defined, the test runner will run that method @@ -2147,22 +2242,44 @@ class Test_TestCase(TestCase, TestEquality, TestHashing): events = [] result = LoggingResult(events) - class Foo(unittest.TestCase): - def setUp(self): - events.append('setUp') - - def test(self): - events.append('test') - + class Foo(LoggingTestCase): def tearDown(self): - events.append('tearDown') + super(Foo, self).tearDown() raise RuntimeError('raised by Foo.tearDown') - Foo('test').run(result) + Foo(events).run(result) expected = ['startTest', 'setUp', 'test', 'tearDown', 'addError', 'stopTest'] self.assertEqual(events, expected) + # "When tearDown errors with a default result stopTestRun is still called." + def test_run_call_order__error_in_tearDown_default_result(self): + + class Foo(LoggingTestCase): + def defaultTestResult(self): + return LoggingResult(self.events) + def tearDown(self): + super(Foo, self).tearDown() + raise RuntimeError('raised by Foo.tearDown') + + events = [] + Foo(events).run() + expected = ['startTestRun', 'startTest', 'setUp', 'test', 'tearDown', + 'addError', 'stopTest', 'stopTestRun'] + self.assertEqual(events, expected) + + # "TestCase.run() still works when the defaultTestResult is a TestResult + # that does not support startTestRun and stopTestRun. + def test_run_call_order_default_result(self): + + class Foo(unittest.TestCase): + def defaultTestResult(self): + return ResultWithNoStartTestRunStopTestRun() + def test(self): + pass + + Foo('test').run() + # "This class attribute gives the exception raised by the test() method. # If a test framework needs to use a specialized exception, possibly to # carry additional information, it must subclass this exception in @@ -2253,7 +2370,9 @@ class Test_TestCase(TestCase, TestEquality, TestHashing): self.failUnless(isinstance(Foo().id(), str)) # "If result is omitted or None, a temporary result object is created - # and used, but is not made available to the caller" + # and used, but is not made available to the caller. As TestCase owns the + # temporary result startTestRun and stopTestRun are called. + def test_run__uses_defaultTestResult(self): events = [] @@ -2267,7 +2386,8 @@ class Test_TestCase(TestCase, TestEquality, TestHashing): # Make run() find a result object on its own Foo('test').run() - expected = ['startTest', 'test', 'addSuccess', 'stopTest'] + expected = ['startTestRun', 'startTest', 'test', 'addSuccess', + 'stopTest', 'stopTestRun'] self.assertEqual(events, expected) def testShortDescriptionWithoutDocstring(self): @@ -3012,6 +3132,220 @@ class TestLongMessage(TestCase): "^unexpectedly identical: None : oops$"]) +class TestCleanUp(TestCase): + + def testCleanUp(self): + class TestableTest(TestCase): + def testNothing(self): + pass + + test = TestableTest('testNothing') + self.assertEqual(test._cleanups, []) + + cleanups = [] + + def cleanup1(*args, **kwargs): + cleanups.append((1, args, kwargs)) + + def cleanup2(*args, **kwargs): + cleanups.append((2, args, kwargs)) + + test.addCleanup(cleanup1, 1, 2, 3, four='hello', five='goodbye') + test.addCleanup(cleanup2) + + self.assertEqual(test._cleanups, + [(cleanup1, (1, 2, 3), dict(four='hello', five='goodbye')), + (cleanup2, (), {})]) + + result = test.doCleanups() + self.assertTrue(result) + + self.assertEqual(cleanups, [(2, (), {}), (1, (1, 2, 3), dict(four='hello', five='goodbye'))]) + + def testCleanUpWithErrors(self): + class TestableTest(TestCase): + def testNothing(self): + pass + + class MockResult(object): + errors = [] + def addError(self, test, exc_info): + self.errors.append((test, exc_info)) + + result = MockResult() + test = TestableTest('testNothing') + test._result = result + + exc1 = Exception('foo') + exc2 = Exception('bar') + def cleanup1(): + raise exc1 + + def cleanup2(): + raise exc2 + + test.addCleanup(cleanup1) + test.addCleanup(cleanup2) + + self.assertFalse(test.doCleanups()) + + (test1, (Type1, instance1, _)), (test2, (Type2, instance2, _)) = reversed(MockResult.errors) + self.assertEqual((test1, Type1, instance1), (test, Exception, exc1)) + self.assertEqual((test2, Type2, instance2), (test, Exception, exc2)) + + def testCleanupInRun(self): + blowUp = False + ordering = [] + + class TestableTest(TestCase): + def setUp(self): + ordering.append('setUp') + if blowUp: + raise Exception('foo') + + def testNothing(self): + ordering.append('test') + + def tearDown(self): + ordering.append('tearDown') + + test = TestableTest('testNothing') + + def cleanup1(): + ordering.append('cleanup1') + def cleanup2(): + ordering.append('cleanup2') + test.addCleanup(cleanup1) + test.addCleanup(cleanup2) + + def success(some_test): + self.assertEqual(some_test, test) + ordering.append('success') + + result = unittest.TestResult() + result.addSuccess = success + + test.run(result) + self.assertEqual(ordering, ['setUp', 'test', 'tearDown', + 'cleanup2', 'cleanup1', 'success']) + + blowUp = True + ordering = [] + test = TestableTest('testNothing') + test.addCleanup(cleanup1) + test.run(result) + self.assertEqual(ordering, ['setUp', 'cleanup1']) + + +class Test_TestProgram(TestCase): + + # Horrible white box test + def testNoExit(self): + result = object() + test = object() + + class FakeRunner(object): + def run(self, test): + self.test = test + return result + + runner = FakeRunner() + + try: + oldParseArgs = TestProgram.parseArgs + TestProgram.parseArgs = lambda *args: None + TestProgram.test = test + + program = TestProgram(testRunner=runner, exit=False) + + self.assertEqual(program.result, result) + self.assertEqual(runner.test, test) + + finally: + TestProgram.parseArgs = oldParseArgs + del TestProgram.test + + + class FooBar(unittest.TestCase): + def testPass(self): + assert True + def testFail(self): + assert False + + class FooBarLoader(unittest.TestLoader): + """Test loader that returns a suite containing FooBar.""" + def loadTestsFromModule(self, module): + return self.suiteClass( + [self.loadTestsFromTestCase(Test_TestProgram.FooBar)]) + + + def test_NonExit(self): + program = unittest.main(exit=False, + argv=["foobar"], + testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testLoader=self.FooBarLoader()) + self.assertTrue(hasattr(program, 'result')) + + + def test_Exit(self): + self.assertRaises( + SystemExit, + unittest.main, + argv=["foobar"], + testRunner=unittest.TextTestRunner(stream=io.StringIO()), + exit=True, + testLoader=self.FooBarLoader()) + + + def test_ExitAsDefault(self): + self.assertRaises( + SystemExit, + unittest.main, + argv=["foobar"], + testRunner=unittest.TextTestRunner(stream=io.StringIO()), + testLoader=self.FooBarLoader()) + + +class Test_TextTestRunner(TestCase): + """Tests for TextTestRunner.""" + + def test_works_with_result_without_startTestRun_stopTestRun(self): + class OldTextResult(ResultWithNoStartTestRunStopTestRun): + separator2 = '' + def printErrors(self): + pass + + class Runner(unittest.TextTestRunner): + def __init__(self): + super(Runner, self).__init__(io.StringIO()) + + def _makeResult(self): + return OldTextResult() + + runner = Runner() + runner.run(unittest.TestSuite()) + + def test_startTestRun_stopTestRun_called(self): + class LoggingTextResult(LoggingResult): + separator2 = '' + def printErrors(self): + pass + + class LoggingRunner(unittest.TextTestRunner): + def __init__(self, events): + super(LoggingRunner, self).__init__(io.StringIO()) + self._events = events + + def _makeResult(self): + return LoggingTextResult(self._events) + + events = [] + runner = LoggingRunner(events) + runner.run(unittest.TestSuite()) + expected = ['startTestRun', 'stopTestRun'] + self.assertEqual(events, expected) + + ###################################################################### ## Main ###################################################################### @@ -3019,7 +3353,8 @@ class TestLongMessage(TestCase): def test_main(): support.run_unittest(Test_TestCase, Test_TestLoader, Test_TestSuite, Test_TestResult, Test_FunctionTestCase, - Test_TestSkipping, Test_Assertions, TestLongMessage) + Test_TestSkipping, Test_Assertions, TestLongMessage, + Test_TestProgram, TestCleanUp) if __name__ == "__main__": test_main() |