Rev 2467: Update TestLoader with functionality to auto-find tests to run. in http://bzr.arbash-meinel.com/branches/bzr/0.17-dev/test_autoloader
John Arbash Meinel
john at arbash-meinel.com
Fri Apr 27 21:31:33 BST 2007
At http://bzr.arbash-meinel.com/branches/bzr/0.17-dev/test_autoloader
------------------------------------------------------------
revno: 2467
revision-id: john at arbash-meinel.com-20070427203112-y3n41qkr3y9nlr20
parent: pqm at pqm.ubuntu.com-20070426211103-h84prqh7a4ad3ez2
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: test_autoloader
timestamp: Fri 2007-04-27 15:31:12 -0500
message:
Update TestLoader with functionality to auto-find tests to run.
added:
bzrlib/tests/test_test_util.py test_test_util.py-20070427203042-9m1ldokoqp9hsdwg-1
modified:
bzrlib/tests/TestUtil.py TestUtil.py-20050824080200-5f70140a2d938694
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
-------------- next part --------------
=== added file 'bzrlib/tests/test_test_util.py'
--- a/bzrlib/tests/test_test_util.py 1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/test_test_util.py 2007-04-27 20:31:12 +0000
@@ -0,0 +1,141 @@
+# Copyright (C) 2007 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Test the TestUtil functions and classes.
+
+This tests things like the ability to automatically find test cases.
+"""
+
+import os
+import sys
+
+from bzrlib import tests
+
+
+class TestFindTestFiles(tests.TestCaseInTempDir):
+ """Test that we can find appropriate test files."""
+
+ def assertFindTestFiles(self, files, packages, path):
+ self.assertEqual((files, packages),
+ tests.TestLoader.find_test_files(path))
+
+ def test_none(self):
+ self.assertFindTestFiles([], [], '.')
+
+ def test_one(self):
+ self.build_tree(['test_foo.py'])
+ self.assertFindTestFiles(['test_foo.py'], [], '.')
+
+ def test_non_package_dir(self):
+ """Only consider it a package if there is an __init__.py"""
+ self.build_tree(['bar/', 'bar/foo', 'bar/baz.py'])
+ self.assertFindTestFiles([], [], '.')
+
+ def test_package(self):
+ self.build_tree(['bar/', 'bar/__init__.py'])
+ self.assertFindTestFiles([], ['bar'], '.')
+
+ def test_subdir(self):
+ self.build_tree(['bar/', 'bar/test_baz.py', 'bar/foo/',
+ 'bar/foo/__init__.py'
+ ])
+ self.assertFindTestFiles(['test_baz.py'], ['foo'], 'bar')
+
+
+class TestRecursiveLoadTests(tests.TestCaseInTempDir):
+
+ def assertRecursiveLoadTests(self, expected_tests, path):
+ """Assert that recursiveLoadTests works.
+
+ :param expected_tests: A list of test ids that should be loaded.
+ :param path: The path to test files. It is assumed this is a single
+ directory name, so that the python name and the filesystem
+ name are identical.
+ """
+ # Make sure it isn't loaded already.
+ self.assertFalse(path in sys.modules)
+ cwd = os.getcwd()
+ sys.path.insert(0, cwd)
+ module_keys = set(sys.modules.keys())
+ try:
+ loader = tests.TestLoader()
+ suite = loader.recursiveLoadTests(path, path)
+ self.assertIsInstance(suite, tests.TestSuite)
+ self.assertEqual(expected_tests,
+ [t.id() for t in tests.iter_suite_tests(suite)])
+ finally:
+ sys.path.remove(cwd)
+ new_keys = set(sys.modules.keys())
+ for mod in new_keys - module_keys:
+ del sys.modules[mod]
+
+ def test_find_none(self):
+ self.build_tree(['test1/'])
+ self.assertRecursiveLoadTests([], 'test1')
+
+ def test_find_file(self):
+ self.build_tree(['loader_test/'])
+ self.build_tree_contents([
+ ('loader_test/__init__.py', ''),
+ ('loader_test/test_foo.py',
+ 'import unittest\n'
+ 'class TestFoo(unittest.TestCase):\n'
+ ' def test_one(self):\n'
+ ' pass\n'
+ ),
+ ])
+ self.assertRecursiveLoadTests(
+ ['loader_test.test_foo.TestFoo.test_one'],
+ 'loader_test')
+
+ def test_find_package(self):
+ self.build_tree(['loader_test/', 'loader_test/package/'])
+ self.build_tree_contents([
+ ('loader_test/__init__.py', ''),
+ ('loader_test/package/__init__.py',
+ 'import unittest\n'
+ 'class TestFoo(unittest.TestCase):\n'
+ ' def test_one(self):\n'
+ ' pass\n'
+ 'class TestBar(unittest.TestCase):\n'
+ ' def test_two(self):\n'
+ ' pass\n'
+ '\n'
+ 'def test_suite():\n'
+ ' # return TestFoo, but not TestBar\n'
+ ' loader = unittest.TestLoader()\n'
+ ' return loader.loadTestsFromTestCase(TestFoo)\n'
+ ),
+ ])
+ self.assertRecursiveLoadTests(
+ ['loader_test.package.TestFoo.test_one'],
+ 'loader_test')
+
+ def test_ignore_no_test_suite(self):
+ self.build_tree(['loader_test/', 'loader_test/package/'])
+ self.build_tree_contents([
+ ('loader_test/__init__.py', ''),
+ ('loader_test/package/__init__.py',
+ 'import unittest\n'
+ 'class TestFoo(unittest.TestCase):\n'
+ ' def test_one(self):\n'
+ ' pass\n'
+ 'class TestBar(unittest.TestCase):\n'
+ ' def test_two(self):\n'
+ ' pass\n'
+ ),
+ ])
+ self.assertRecursiveLoadTests([], 'loader_test')
=== modified file 'bzrlib/tests/TestUtil.py'
--- a/bzrlib/tests/TestUtil.py 2007-04-23 03:41:48 +0000
+++ b/bzrlib/tests/TestUtil.py 2007-04-27 20:31:12 +0000
@@ -16,8 +16,9 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
+import logging
+import os
import sys
-import logging
import unittest
# Mark this python module as being part of the implementation
@@ -90,6 +91,59 @@
result.addTests(self.loadTestsFromName(name))
return result
+ @staticmethod
+ def find_test_files(base):
+ """Find test files for all files underneath a given directory.
+
+ :param base: A base directory to look for files and subdirs.
+ :return: ([test_files], [packages]) A list of test files and python
+ packages (dirs with __init__.py) that should contain tests.
+ """
+ names = []
+ # Packages are assumed to have their own 'test_suite' function
+ packages = []
+ for name in os.listdir(base):
+ path = os.path.join(base, name)
+ if os.path.isdir(path):
+ init_path = os.path.join(path, '__init__.py')
+ if os.path.isfile(init_path):
+ packages.append(name)
+ else:
+ if name.startswith('test') and name.endswith('.py'):
+ names.append(name)
+ return names, packages
+
+ def recursiveLoadTests(self, base, python_base):
+ """Load all test cases that are underneath base.
+
+ Any test_*.py files in the base directory will be loaded directly. For
+ python packages, they will be loaded and package.test_suite() will be
+ run to get a TestSuite that should be run.
+
+ :param base: The base directory to start looking.
+ :param python_base: The python name matching the base directory.
+ :return: a TestSuite() with all the tests loaded.
+
+ Example:
+ loader = TestLoader()
+ cur_dir = os.path.basename(__file__)
+ loader.recursiveLoadTests(cur_dir, __name__)
+ """
+ names, packages = self.find_test_files(base)
+ modules = []
+ for name in names:
+ assert name.endswith('.py')
+ full_python_name = python_base + '.' + name[:-3]
+ modules.append(full_python_name)
+ suite = self.loadTestsFromNames(modules)
+ for package in packages:
+ pkg_name = python_base + '.' + package
+ pkg = __import__(pkg_name, {}, {}, ['test_suite'])
+ test_suite = getattr(pkg, 'test_suite', None)
+ if test_suite is not None:
+ suite.addTests(test_suite())
+ return suite
+
def _load_module_by_name(mod_name):
parts = mod_name.split('.')
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2007-04-26 09:07:38 +0000
+++ b/bzrlib/tests/__init__.py 2007-04-27 20:31:12 +0000
@@ -2349,6 +2349,7 @@
'bzrlib.tests.test_subsume',
'bzrlib.tests.test_symbol_versioning',
'bzrlib.tests.test_tag',
+ 'bzrlib.tests.test_test_util',
'bzrlib.tests.test_testament',
'bzrlib.tests.test_textfile',
'bzrlib.tests.test_textmerge',
More information about the bazaar-commits
mailing list