Rev 2934: * Modules can now customise their tests by defining a ``load_tests`` in http://people.ubuntu.com/~robertc/baz2.0/delegate-test-suite

Robert Collins robertc at robertcollins.net
Tue Dec 18 07:29:43 GMT 2007


At http://people.ubuntu.com/~robertc/baz2.0/delegate-test-suite

------------------------------------------------------------
revno: 2934
revision-id:robertc at robertcollins.net-20071218072914-4u8lpcxet9umd1sg
parent: robertc at robertcollins.net-20071218053755-g7ksomxlee02swb4
committer: Robert Collins <robertc at robertcollins.net>
branch nick: delegate-test-suite
timestamp: Tue 2007-12-18 18:29:14 +1100
message:
  * Modules can now customise their tests by defining a ``load_tests``
    attribute. ``pydoc bzrlib.tests.TestUtil.TestLoader.loadTestsFromModule``
    for the documentation on this attribute. (Robert Collins)
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/tests/TestUtil.py       TestUtil.py-20050824080200-5f70140a2d938694
  bzrlib/tests/test_selftest.py  test_selftest.py-20051202044319-c110a115d8c0456a
=== modified file 'NEWS'
--- a/NEWS	2007-12-18 05:37:55 +0000
+++ b/NEWS	2007-12-18 07:29:14 +0000
@@ -72,6 +72,10 @@
 
   TESTING:
 
+   * Modules can now customise their tests by defining a ``load_tests``
+     attribute. ``pydoc bzrlib.tests.TestUtil.TestLoader.loadTestsFromModule``
+     for the documentation on this attribute. (Robert Collins)
+
    * New helper function ``bzrlib.tests.condition_id_re`` which helps
      filter tests based on a regular expression search on the tests id.
      (Robert Collins)

=== modified file 'bzrlib/tests/TestUtil.py'
--- a/bzrlib/tests/TestUtil.py	2007-04-23 03:41:48 +0000
+++ b/bzrlib/tests/TestUtil.py	2007-12-18 07:29:14 +0000
@@ -74,7 +74,8 @@
 
 
 class TestLoader(unittest.TestLoader):
-    """Custom  TestLoader to address some quirks in the stock python one."""
+    """Custom TestLoader to extend the stock python one."""
+
     suiteClass = TestSuite
 
     def loadTestsFromModuleNames(self, names):
@@ -86,10 +87,41 @@
         """
         result = self.suiteClass()
         for name in names:
-            _load_module_by_name(name)
-            result.addTests(self.loadTestsFromName(name))
+            module = _load_module_by_name(name)
+            result.addTests(self.loadTestsFromModule(module))
         return result
 
+    def loadTestsFromModule(self, module):
+        """Load tests from a module object.
+
+        This extension of the python test loader looks for an attribute
+        load_tests in the module object, and if not found falls back to the
+        regular python loadTestsFromModule.
+
+        If a load_tests attribute is found, it is called and the result is
+        returned. 
+
+        load_tests should be defined like so:
+        >>> def load_tests(standard_tests, module, loader):
+        >>>    pass
+
+        standard_tests is the tests found by the stock TestLoader in the
+        module, module and loader are the module and loader instances.
+
+        For instance, to run every test twice, you might do:
+        >>> def load_tests(standard_tests, module, loader):
+        >>>     result = loader.suiteClass()
+        >>>     for test in iter_suite_tests(standard_tests):
+        >>>         result.addTests([test, test])
+        >>>     return result
+        """
+        basic_tests = super(TestLoader, self).loadTestsFromModule(module)
+        load_tests = getattr(module, "load_tests", None)
+        if load_tests is not None:
+            return load_tests(basic_tests, module, self)
+        else:
+            return basic_tests
+
 
 def _load_module_by_name(mod_name):
     parts = mod_name.split('.')

=== modified file 'bzrlib/tests/test_selftest.py'
--- a/bzrlib/tests/test_selftest.py	2007-12-18 05:37:55 +0000
+++ b/bzrlib/tests/test_selftest.py	2007-12-18 07:29:14 +0000
@@ -1806,3 +1806,38 @@
         out, err = self.run_bzr(["log", "/nonexistantpath"], retcode=3)
         self.assertEqual(out, '')
         self.assertEqual(err, 'bzr: ERROR: Not a branch: "/nonexistantpath/".\n')
+
+
+class TestTestLoader(TestCase):
+    """Tests for the test loader."""
+
+    def _get_loader_and_module(self):
+        """Gets a TestLoader and a module with one test in it."""
+        loader = TestUtil.TestLoader()
+        module = {}
+        class Stub(TestCase):
+            def test_foo(self):
+                pass
+        class MyModule(object):
+            pass
+        MyModule.a_class = Stub
+        module = MyModule()
+        return loader, module
+
+    def test_module_no_load_tests_attribute_loads_classes(self):
+        loader, module = self._get_loader_and_module()
+        self.assertEqual(1, loader.loadTestsFromModule(module).countTestCases())
+
+    def test_module_load_tests_attribute_gets_called(self):
+        loader, module = self._get_loader_and_module()
+        # 'self' is here because we're faking the module with a class. Regular
+        # load_tests do not need that :)
+        def load_tests(self, standard_tests, module, loader):
+            result = loader.suiteClass()
+            for test in iter_suite_tests(standard_tests):
+                result.addTests([test, test])
+            return result
+        # add a load_tests() method which multiplies the tests from the module.
+        module.__class__.load_tests = load_tests
+        self.assertEqual(2, loader.loadTestsFromModule(module).countTestCases())
+



More information about the bazaar-commits mailing list