diff options
author | Robert Collins <robertc@robertcollins.net> | 2009-06-17 19:11:03 +1000 |
---|---|---|
committer | Robert Collins <robertc@robertcollins.net> | 2009-06-17 19:11:03 +1000 |
commit | b571a618c617fb02805731eab238baa75c5a4179 (patch) | |
tree | ee118fc2ce35a14d46e2c6852ec73e66286929a5 | |
parent | 517ce1f70cb7a969b808a0445dd75c278f61ff69 (diff) | |
parent | 58b817afeb8b95e35d5a6347266316b9f35a3465 (diff) | |
download | testresources-b571a618c617fb02805731eab238baa75c5a4179.tar.gz |
Merge adsorbSuite->addTests rename.
-rw-r--r-- | NEWS | 7 | ||||
-rw-r--r-- | README | 8 | ||||
-rw-r--r-- | TODO | 24 | ||||
-rw-r--r-- | lib/testresources/__init__.py | 39 | ||||
-rw-r--r-- | lib/testresources/tests/test_optimising_test_suite.py | 57 | ||||
-rwxr-xr-x | test_all.py | 2 |
6 files changed, 80 insertions, 57 deletions
@@ -31,6 +31,13 @@ IN DEVELOPMENT API CHANGES: + * adsorbSuite is now deprecated in favour of addTest. addTest now flattens + standard library TestSuites and distributes custom TestSuite across + their member tests. (Jonathan Lange) + + * ResourcedTestCase.setUpResources and tearDownResources are now instance + methods, not static methods. (Jonathan Lange) + * All methods on TestResource are now instance methods, and thus tests should use instances of TestResource subclasses, not the classes themselves. (Jonathan Lange) @@ -73,9 +73,11 @@ minimise the number of setup and tear downs required. It attempts to achieve this by callling getResource() and finishedWith() around the sequence of tests that use a specific resource. -OptimisingTestSuite has a new method over normal TestSuites: -adsorbSuite(test_case_or_suite), which scans another test suite and -incorporates all of its tests directly into the OptimisingTestSuite. +Tests are added to an OptimisingTestSuite as normal. Any standard library +TestSuite objects will be flattened, while any custom TestSuite subclasses +will be distributed across their member tests. This means that any custom +logic in test suites should be preserved, at the price of some level of +optimisation. Because the test suite does the optimisation, you can control the amount of optimising that takes place by adding more or fewer tests to a single @@ -50,30 +50,6 @@ Ideas * There are now many simple test helpers. These can probably be consolidated. -* We want to support adding other "special" test suites to - OptimisingTestSuite. In particular, if we add a test suite that provides - services to its tests to an OptimisingTestSuite, adsorbSuite should not - totally flatten the suite, but instead keep the suite, even if it changes - the structure of the tests. - - e.g. addTest maintains the structure: - >>> OptimisingTestSuite().addTest(SpecialSuite([a, b]))._tests - [SpecialSuite([a, b])] - - Currently, adsorbSuite destroys all suite structure: - >>> OptimisingTestSuite().adsorbSuite(SpecialSuite([a, b]))._tests - [a, b] - - Instead, it should preserve the suite while changing the structure: - >>> OptimisingTestSuite().adsorbSuite(SpecialSuite([a, b]))._tests - [SpecialSuite(a), SpecialSuite(b)] - - All of the tests in each of the resulting new SpecialSuites should have - identical resource requirements so we can still optimise. - - Once it does this, we should deprecate adsorbSuite and move this - functionality to addTest / addTests. - * 'TestResource' isn't a very good name. Since the switch to instance-based resources, it's even worse, since the objects are more like resource factories or resource managers. Other possible names involve 'asset', diff --git a/lib/testresources/__init__.py b/lib/testresources/__init__.py index 2f317ea..5a5aa15 100644 --- a/lib/testresources/__init__.py +++ b/lib/testresources/__init__.py @@ -25,18 +25,6 @@ def test_suite(): return testresources.tests.test_suite() -def iterate_tests(test_suite_or_case): - """Iterate through all of the test cases in `test_suite_or_case`.""" - try: - suite = iter(test_suite_or_case) - except TypeError: - yield test_suite_or_case - else: - for test in suite: - for subtest in iterate_tests(test): - yield subtest - - def split_by_resources(tests): """Split a list of tests by the resources that the tests use. @@ -60,14 +48,29 @@ class OptimisingTestSuite(unittest.TestSuite): """A resource creation optimising TestSuite.""" def adsorbSuite(self, test_case_or_suite): - """Add `test_case_or_suite`, unwrapping any suites we find. + """Deprecated. Use addTest instead.""" + self.addTest(test_case_or_suite) + + def addTest(self, test_case_or_suite): + """Add `test_case_or_suite`, unwrapping standard TestSuites. - This means that any containing TestSuites will be removed. These - suites might have their own unittest extensions, so be careful with - this. + This means that any containing unittest.TestSuites will be removed, + while any custom test suites will be 'distributed' across their + members. Thus addTest(CustomSuite([a, b])) will result in + CustomSuite([a]) and CustomSuite([b]) being added to this suite. """ - for test in iterate_tests(test_case_or_suite): - self.addTest(test) + try: + tests = iter(test_case_or_suite) + except TypeError: + unittest.TestSuite.addTest(self, test_case_or_suite) + return + if unittest.TestSuite == test_case_or_suite.__class__: + for test in tests: + self.adsorbSuite(test) + else: + for test in tests: + unittest.TestSuite.addTest( + self, test_case_or_suite.__class__([test])) def cost_of_switching(self, old_resource_set, new_resource_set): """Cost of switching from 'old_resource_set' to 'new_resource_set'. diff --git a/lib/testresources/tests/test_optimising_test_suite.py b/lib/testresources/tests/test_optimising_test_suite.py index 4bf06d3..fddbb5f 100644 --- a/lib/testresources/tests/test_optimising_test_suite.py +++ b/lib/testresources/tests/test_optimising_test_suite.py @@ -32,6 +32,16 @@ def test_suite(): return result +class CustomSuite(unittest.TestSuite): + """Custom TestSuite that's comparable using == and !=.""" + + def __eq__(self, other): + return (self.__class__ == other.__class__ + and self._tests == other._tests) + def __ne__(self, other): + return not self.__eq__(other) + + class MakeCounter(testresources.TestResource): """Test resource that counts makes and cleans.""" @@ -71,33 +81,58 @@ class TestOptimisingTestSuite(testtools.TestCase): testtools.TestCase.setUp(self) self.optimising_suite = testresources.OptimisingTestSuite() - def testAdsorbTest(self): - # Adsorbing a single test case is the same as adding one using - # addTest. + def testAddTest(self): + # Adding a single test case is the same as adding one using the + # standard addTest. case = self.makeTestCase() - self.optimising_suite.adsorbSuite(case) + self.optimising_suite.addTest(case) self.assertEqual([case], self.optimising_suite._tests) - def testAdsorbTestSuite(self): - # Adsorbing a test suite will is the same as adding all the tests in + def testAddTestSuite(self): + # Adding a standard test suite is the same as adding all the tests in # that suite. case = self.makeTestCase() suite = unittest.TestSuite([case]) - self.optimising_suite.adsorbSuite(suite) + self.optimising_suite.addTest(suite) self.assertEqual([case], self.optimising_suite._tests) - def testAdsorbFlattensAllSuiteStructure(self): - # adsorbSuite will get rid of all suite structure when adding a test, - # no matter how much nesting is going on. + def testAddFlattensStandardSuiteStructure(self): + # addTest will get rid of all unittest.TestSuite structure when adding + # a test, no matter how much nesting is going on. case1 = self.makeTestCase() case2 = self.makeTestCase() case3 = self.makeTestCase() suite = unittest.TestSuite( [unittest.TestSuite([case1, unittest.TestSuite([case2])]), case3]) - self.optimising_suite.adsorbSuite(suite) + self.optimising_suite.addTest(suite) self.assertEqual([case1, case2, case3], self.optimising_suite._tests) + def testAddDistributesNonStandardSuiteStructure(self): + # addTest distributes all non-standard TestSuites across their + # members. + case1 = self.makeTestCase() + case2 = self.makeTestCase() + inner_suite = unittest.TestSuite([case2]) + suite = CustomSuite([case1, inner_suite]) + self.optimising_suite.addTest(suite) + self.assertEqual( + [CustomSuite([case1]), CustomSuite([inner_suite])], + self.optimising_suite._tests) + + def testAddPullsNonStandardSuitesUp(self): + # addTest flattens standard TestSuites, even those that contain custom + # suites. When it reaches the custom suites, it distributes them + # across their members. + case1 = self.makeTestCase() + case2 = self.makeTestCase() + inner_suite = CustomSuite([case1, case2]) + self.optimising_suite.addTest( + unittest.TestSuite([unittest.TestSuite([inner_suite])])) + self.assertEqual( + [CustomSuite([case1]), CustomSuite([case2])], + self.optimising_suite._tests) + def testSingleCaseResourceAcquisition(self): sample_resource = MakeCounter() def getResourceCount(): diff --git a/test_all.py b/test_all.py index c0288bd..e265c90 100755 --- a/test_all.py +++ b/test_all.py @@ -54,7 +54,7 @@ class EarlyStoppingTextTestResult(unittest._TextTestResult): self.stop() def addFailure(self, test, err): - unittest._TextTestResult.addError(self, test, err) + unittest._TextTestResult.addFailure(self, test, err) if self.stopOnFailure(): self.stop() |