Rev 3204: Relax constraint on test ids, simplify implementation and update tests. in file:///v/home/vila/src/bzr/experimental/selftest/
Vincent Ladeuil
v.ladeuil+lp at free.fr
Mon Jan 21 14:49:23 GMT 2008
At file:///v/home/vila/src/bzr/experimental/selftest/
------------------------------------------------------------
revno: 3204
revision-id:v.ladeuil+lp at free.fr-20080121144918-xx5wtw3ddfm0iauh
parent: v.ladeuil+lp at free.fr-20080121112100-8qaiys24wb2nqowe
committer: Vincent Ladeuil <v.ladeuil+lp at free.fr>
branch nick: selftest
timestamp: Mon 2008-01-21 15:49:18 +0100
message:
Relax constraint on test ids, simplify implementation and update tests.
* bzrlib/tests/test_selftest.py:
(TestSelftestFiltering.test_condition_id_in_list,
TestSelftestFiltering.test_filter_suite_by_id_list): Updated.
(TestTestIdList): Renamed from TestTestIdListFilter and updated.
* bzrlib/tests/__init__.py:
(TestIdList): Relax the constraint on test ids, they just have to
start with their module name.
* bzrlib/doc/api/__init__.py:
(test_suite): Adding module name in test id is now enough.
modified:
bzrlib/doc/api/__init__.py __init__.py-20051224020744-7b87d590843855bc
bzrlib/tests/__init__.py selftest.py-20050531073622-8d0e3c8845c97a64
bzrlib/tests/test_selftest.py test_selftest.py-20051202044319-c110a115d8c0456a
-------------- next part --------------
=== modified file 'bzrlib/doc/api/__init__.py'
--- a/bzrlib/doc/api/__init__.py 2008-01-21 11:18:27 +0000
+++ b/bzrlib/doc/api/__init__.py 2008-01-21 14:49:18 +0000
@@ -38,14 +38,11 @@
scripts = [candidate for candidate in candidates
if candidate.endswith('.txt')]
suite = doctest.DocFileSuite(*scripts)
- # DocFileCase reduces the test id to the base file name, we want more
+ # DocFileCase reduces the test id to the base name of the tested file, we
+ # want the module to appears there.
for t in tests.iter_suite_tests(suite):
def make_new_test_id():
- # While complying with the rule that a test id is
- # <module>.<class>.<method>[(<param>+)], this does not represent
- # the python names for class and method but should give enough
- # hints to find back the source of a failing test.
- new_id = '%s.DocFileCase.DocFileTest(%s)' % ( __name__, t)
+ new_id = '%s(%s)' % ( __name__, t)
return lambda: new_id
t.id = make_new_test_id()
return suite
=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py 2008-01-21 11:18:27 +0000
+++ b/bzrlib/tests/__init__.py 2008-01-21 14:49:18 +0000
@@ -2261,14 +2261,14 @@
return condition
-def condition_id_in_list(name_list):
+def condition_id_in_list(id_list):
"""Create a condition filter which verify that test's id in a list.
- :param name: A list of test names.
+ :param name: A TestIdList object.
:return: A callable that returns True if the test's id appears in the list.
"""
def condition(test):
- return test.id() in name_list
+ return id_list.test_in(test.id())
return condition
@@ -2584,77 +2584,48 @@
return test_list
-class TestIdListFilter(object):
- """Test suite filter against a test id list.
+class TestIdList(object):
+ """Test id list to filter a test suite.
Relying on the assumption that test ids are built as:
- <module>.<class>.<method>[(<param>+)], this class offers methods to :
+ <module>[.<class>.<method>][(<param>+)], <module> being in python dotted
+ notation, this class offers methods to :
- avoid building a test suite for modules not refered to in the test list,
- keep only the tests listed from the module test suite.
"""
def __init__(self, test_id_list):
- by_modules = {}
+ # When a test suite needs to be filtered against us we compare test ids
+ # for equality, so a simple dict offers a quick and simple solution.
+ self.tests = dict().fromkeys(test_id_list, True)
+
+ # While unittest.TestCase have ids like:
+ # <module>.<class>.<method>[(<param+)],
+ # doctest.DocTestCase can have ids like:
+ # <module>
+ # <module>.<class>
+ # <module>.<function>
+ # <module>.<class>.<method>
+
+ # Since we can't predict a test class from its name only, we settle on
+ # a simple constraint: a test id always begins with its module name.
+
+ modules = {}
for test_id in test_id_list:
- if '(' in test_id:
- # Get read of params in case they contain '.' chars
- name, params = test_id.split('(')
- else:
- name = test_id
- try:
- mod_name, klass, meth_name = name.rsplit('.', 2)
- except ValueError:
- # Not enough components. Put the test in the "empty" module
- # since we can't reliably find its associated module.
- mod_name = ''
- by_module = by_modules.get(mod_name, None)
- if by_module is None:
- by_modules[mod_name] = [test_id]
- else:
- by_module.append(test_id)
- self.tests_by_modules = by_modules
-
- by_bases = {}
- for module_name in by_modules.keys():
- base = module_name
- while base:
- by_base = by_bases.get(base, None)
- if by_base is None:
- by_bases[base] = [module_name]
- else:
- by_base.append(module_name)
- try:
- base, sub_mod_name = base.rsplit('.', 1)
- except ValueError:
- base = None
- self.module_hierarchies = by_bases
-
- def used_modules(self):
- """Return the modules containing the test classes."""
- return self.tests_by_modules.keys()
-
- def get_tests(self, module_name):
- """Return tests defined in the module itself."""
- return self.tests_by_modules.get(module_name, [])
-
- def get_tests_under(self, module_name):
- """Return tests defined in the module or one of its submodules."""
- tests_list = []
- for mod in self.module_hierarchies.get(module_name, []):
- tests_list.extend(self.get_tests(mod))
- return tests_list
+ parts = test_id.split('.')
+ mod_name = parts.pop(0)
+ modules[mod_name] = True
+ for part in parts:
+ mod_name += '.' + part
+ modules[mod_name] = True
+ self.modules = modules
def is_module_name_used(self, module_name):
"""Is there tests for the module or one of its sub modules."""
- return self.module_hierarchies.has_key(module_name)
-
- def for_module_and_below(self, module_name, suite):
- """Filter a test suite by a module name.
-
- Returns tests defined in a module or one of its sub modules.
- """
- return filter_suite_by_id_list(suite,
- self.get_tests_under(module_name))
+ return self.modules.has_key(module_name)
+
+ def test_in(self, test_id):
+ return self.tests.has_key(test_id)
def test_suite(keep_only=None):
@@ -2802,7 +2773,7 @@
loader = TestUtil.TestLoader()
if keep_only is not None:
- id_filter = TestIdListFilter(keep_only)
+ id_filter = TestIdList(keep_only)
# modules building their suite with loadTestsFromModuleNames
if keep_only is None:
@@ -2811,7 +2782,7 @@
for mod in [m for m in testmod_names
if id_filter.is_module_name_used(m)]:
mod_suite = loader.loadTestsFromModuleNames([mod])
- mod_suite = id_filter.for_module_and_below(mod, mod_suite)
+ mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
suite.addTest(mod_suite)
# modules adapted for transport implementations
@@ -2824,7 +2795,7 @@
if id_filter.is_module_name_used(m)]:
mod_suite = TestUtil.TestSuite()
adapt_modules([mod], adapter, loader, mod_suite)
- mod_suite = id_filter.for_module_and_below(mod, mod_suite)
+ mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
suite.addTest(mod_suite)
# modules defining their own test_suite()
@@ -2833,8 +2804,7 @@
or id_filter.is_module_name_used(p.__name__))]:
pack_suite = package.test_suite()
if keep_only is not None:
- pack_suite = id_filter.for_module_and_below(package.__name__,
- pack_suite)
+ pack_suite = filter_suite_by_id_list(pack_suite, id_filter)
suite.addTest(pack_suite)
# XXX: MODULES_TO_TEST should be obsoleted ?
@@ -2842,7 +2812,7 @@
if keep_only is None or id_filter.is_module_name_used(m)]:
mod_suite = loader.loadTestsFromModule(mod)
if keep_only is not None:
- mod_suite = id_filter.for_module_and_below(mod, mod_suite)
+ mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
suite.addTest(mod_suite)
for mod in MODULES_TO_DOCTEST:
@@ -2853,7 +2823,7 @@
raise
if keep_only is not None:
# DocTests may use ids which doesn't contain the module name
- doc_suite = filter_suite_by_id_list(doc_suite, keep_only)
+ doc_suite = filter_suite_by_id_list(doc_suite, id_filter)
suite.addTest(doc_suite)
default_encoding = sys.getdefaultencoding()
@@ -2869,8 +2839,8 @@
else:
if plugin_suite is not None:
if keep_only is not None:
- plugin_suite = id_filter.for_module_and_below(
- plugin.module.__name__, plugin_suite)
+ plugin_suite = filter_suite_by_id_list(plugin_suite,
+ id_filter)
suite.addTest(plugin_suite)
if default_encoding != sys.getdefaultencoding():
bzrlib.trace.warning(
=== modified file 'bzrlib/tests/test_selftest.py'
--- a/bzrlib/tests/test_selftest.py 2008-01-21 10:51:02 +0000
+++ b/bzrlib/tests/test_selftest.py 2008-01-21 14:49:18 +0000
@@ -1686,8 +1686,9 @@
def test_condition_id_in_list(self):
test_names = ['bzrlib.tests.test_selftest.TestSelftestFiltering.'
'test_condition_id_in_list']
+ id_list = tests.TestIdList(test_names)
filtered_suite = filter_suite_by_condition(
- self.suite, tests.condition_id_in_list(test_names))
+ self.suite, tests.condition_id_in_list(id_list))
my_pattern = 'TestSelftestFiltering.*test_condition_id_in_list'
re_filtered = filter_suite_by_re(self.suite, my_pattern)
self.assertEqual(self._test_ids(re_filtered),
@@ -1739,10 +1740,10 @@
'TestSelftestFiltering.test_filter_suite_by_re'])
def test_filter_suite_by_id_list(self):
+ test_list = ['bzrlib.tests.test_selftest.'
+ 'TestSelftestFiltering.test_filter_suite_by_id_list']
filtered_suite = tests.filter_suite_by_id_list(
- self.suite,
- ['bzrlib.tests.test_selftest.'
- 'TestSelftestFiltering.test_filter_suite_by_id_list'])
+ self.suite, tests.TestIdList(test_list))
filtered_names = self._test_ids(filtered_suite)
self.assertEqual(
filtered_names,
@@ -1865,12 +1866,12 @@
self.assertEqual(2, loader.loadTestsFromModule(module).countTestCases())
-class TestTestIdListFilter(tests.TestCase):
-
- def _create_filter(self, test_list):
- return tests.TestIdListFilter(test_list)
-
- def _create_suite(self, id_list):
+class TestTestIdList(tests.TestCase):
+
+ def _create_id_list(self, test_list):
+ return tests.TestIdList(test_list)
+
+ def _create_suite(self, test_id_list):
class Stub(TestCase):
def test_foo(self):
@@ -1880,7 +1881,7 @@
return lambda: id
suite = TestUtil.TestSuite()
- for id in id_list:
+ for id in test_id_list:
t = Stub('test_foo')
t.id = _create_test_id(id)
suite.addTest(t)
@@ -1891,85 +1892,34 @@
return [t.id() for t in iter_suite_tests(test_suite)]
def test_empty_list(self):
- filter = self._create_filter([])
- self.assertEquals([], filter.used_modules())
+ id_list = self._create_id_list([])
+ self.assertEquals({}, id_list.tests)
+ self.assertEquals({}, id_list.modules)
def test_valid_list(self):
- filter = self._create_filter(
+ id_list = self._create_id_list(
['mod1.cl1.meth1', 'mod1.cl1.meth2',
- 'mod1.cl2.meth1', 'mod1.cl2.meth2',
+ 'mod1.func1', 'mod1.cl2.meth2',
+ 'mod1.submod1',
'mod1.submod2.cl1.meth1', 'mod1.submod2.cl2.meth2',
])
- self.assertEquals(['mod1', 'mod1.submod2'], filter.used_modules())
- self.assertEquals(['mod1.cl1.meth1', 'mod1.cl1.meth2',
- 'mod1.cl2.meth1', 'mod1.cl2.meth2',],
- filter.get_tests('mod1'))
- self.assertEquals(['mod1.submod2.cl1.meth1', 'mod1.submod2.cl2.meth2'],
- filter.get_tests('mod1.submod2'))
-
- def test_get_tests_under(self):
- filter = self._create_filter(
- ['mod.cl1.meth1','mod.cl2.meth2',
- 'mod.submod.cl1.meth1', 'mod.submod.cl2.meth2',
- 'mod2.cl1.meth1',
- ])
- self.assertEquals(['mod.cl1.meth1', 'mod.cl2.meth2',],
- filter.get_tests('mod'))
- self.assertEquals(['mod.submod.cl1.meth1', 'mod.submod.cl2.meth2'],
- filter.get_tests('mod.submod'))
- self.assertEquals(set(['mod.cl1.meth1','mod.cl2.meth2',
- 'mod.submod.cl1.meth1', 'mod.submod.cl2.meth2']),
- set(filter.get_tests_under('mod')))
-
- def test_too_short_test_name(self):
- filter = self._create_filter(['mod1', 'mod2.method1', 'mod3.cl1'])
- self.assertEquals([''],filter.used_modules())
- self.assertEquals(['mod1', 'mod2.method1', 'mod3.cl1'],
- filter.get_tests(''))
-
+ self.assertTrue(id_list.is_module_name_used('mod1'))
+ self.assertTrue(id_list.is_module_name_used('mod1.submod1'))
+ self.assertTrue(id_list.is_module_name_used('mod1.submod2'))
+ self.assertTrue(id_list.test_in('mod1.cl1.meth1'))
+ self.assertTrue(id_list.test_in('mod1.submod1'))
+ self.assertTrue(id_list.test_in('mod1.func1'))
def test_bad_chars_in_params(self):
- filter = self._create_filter(['mod1.cl1.meth1(xx.yy)'])
- self.assertEquals(['mod1'], filter.used_modules())
- self.assertEquals(['mod1.cl1.meth1(xx.yy)'],
- filter.get_tests('mod1'))
+ id_list = self._create_id_list(['mod1.cl1.meth1(xx.yy)'])
+ self.assertTrue(id_list.is_module_name_used('mod1'))
+ self.assertTrue(id_list.test_in('mod1.cl1.meth1(xx.yy)'))
def test_module_used(self):
- filter = self._create_filter(['mod.class.meth'])
- self.assertTrue(filter.is_module_name_used('mod'))
-
- def test_module_used_includes_sub_modules(self):
- filter = self._create_filter(['mod.sub_mod.class.meth'])
- self.assertTrue(filter.is_module_name_used('mod'))
- self.assertTrue(filter.is_module_name_used('mod.sub_mod'))
-
- def test_module_used_refuses_class(self):
- filter = self._create_filter(['mod.sub_mod.class.meth'])
- self.assertFalse(filter.is_module_name_used('mod.sub_mod.class'))
-
- def test_filter_for_module_and_below(self):
- test_list = ['mod1.cl1.meth1', 'mod1.cl2.meth2',
- 'mod1.submod2.cl1.meth1',
- 'mod2.submod2.cl1.meth2',
- ]
- suite = self._create_suite(test_list)
- filter = self._create_filter(test_list)
- mod1_suite = filter.for_module_and_below('mod1', suite)
- self.assertEquals(['mod1.cl1.meth1', 'mod1.cl2.meth2',
- 'mod1.submod2.cl1.meth1'],
- self._test_ids(mod1_suite))
- mod2_suite = filter.for_module_and_below('mod2', suite)
- self.assertEquals(['mod2.submod2.cl1.meth2'],
- self._test_ids(mod2_suite))
-
- def test_filter_for_module_and_below_empty_result(self):
- test_list = ['mod1.cl1.meth1', 'mod1.cl2.meth2',
- 'mod2.submod2.cl1.meth2',
- ]
- suite = self._create_suite(test_list)
- filter = self._create_filter(test_list)
- mod3_suite = filter.for_module_and_below('mod3', suite)
- self.assertEquals(0, mod3_suite.countTestCases())
+ id_list = self._create_id_list(['mod.class.meth'])
+ self.assertTrue(id_list.is_module_name_used('mod'))
+ self.assertTrue(id_list.is_module_name_used('mod.class'))
+ self.assertTrue(id_list.is_module_name_used('mod.class.meth'))
def test_test_suite(self):
# This test is slow, so we do a single test with one test in each
More information about the bazaar-commits
mailing list