110
107
default_transport = LocalURLServer
113
MODULES_TO_DOCTEST = [
123
bzrlib.version_info_formats.format_custom,
124
# quoted to avoid module-loading circularity
129
def packages_to_test():
130
"""Return a list of packages to test.
132
The packages are not globally imported so that import failures are
133
triggered when running selftest, not when importing the command.
136
import bzrlib.tests.blackbox
137
import bzrlib.tests.branch_implementations
138
import bzrlib.tests.bzrdir_implementations
139
import bzrlib.tests.commands
140
import bzrlib.tests.interrepository_implementations
141
import bzrlib.tests.interversionedfile_implementations
142
import bzrlib.tests.intertree_implementations
143
import bzrlib.tests.inventory_implementations
144
import bzrlib.tests.per_lock
145
import bzrlib.tests.repository_implementations
146
import bzrlib.tests.revisionstore_implementations
147
import bzrlib.tests.tree_implementations
148
import bzrlib.tests.workingtree_implementations
151
bzrlib.tests.blackbox,
152
bzrlib.tests.branch_implementations,
153
bzrlib.tests.bzrdir_implementations,
154
bzrlib.tests.commands,
155
bzrlib.tests.interrepository_implementations,
156
bzrlib.tests.interversionedfile_implementations,
157
bzrlib.tests.intertree_implementations,
158
bzrlib.tests.inventory_implementations,
159
bzrlib.tests.per_lock,
160
bzrlib.tests.repository_implementations,
161
bzrlib.tests.revisionstore_implementations,
162
bzrlib.tests.tree_implementations,
163
bzrlib.tests.workingtree_implementations,
167
110
class ExtendedTestResult(unittest._TextTestResult):
168
111
"""Accepts, reports and accumulates the results of running tests.
416
361
self.pb.update('[test 0/%d] starting...' % (self.num_tests))
418
363
def _progress_prefix_text(self):
419
a = '[%d' % self.count
364
# the longer this text, the less space we have to show the test
366
a = '[%d' % self.count # total that have been run
367
# tests skipped as known not to be relevant are not important enough
369
## if self.skip_count:
370
## a += ', %d skip' % self.skip_count
371
## if self.known_failure_count:
372
## a += '+%dX' % self.known_failure_count
420
373
if self.num_tests is not None:
421
374
a +='/%d' % self.num_tests
422
a += ' in %ds' % (time.time() - self._overall_start_time)
376
runtime = time.time() - self._overall_start_time
378
a += '%dm%ds' % (runtime / 60, runtime % 60)
423
381
if self.error_count:
424
a += ', %d errors' % self.error_count
382
a += ', %d err' % self.error_count
425
383
if self.failure_count:
426
a += ', %d failed' % self.failure_count
427
if self.known_failure_count:
428
a += ', %d known failures' % self.known_failure_count
430
a += ', %d skipped' % self.skip_count
384
a += ', %d fail' % self.failure_count
431
385
if self.unsupported:
432
a += ', %d missing features' % len(self.unsupported)
386
a += ', %d missing' % len(self.unsupported)
2088
2110
def build_tree_contents(self, shape):
2089
2111
build_tree_contents(shape)
2091
def assertFileEqual(self, content, path):
2092
"""Fail if path does not contain 'content'."""
2093
self.failUnlessExists(path)
2094
f = file(path, 'rb')
2099
self.assertEqualDiff(content, s)
2101
def failUnlessExists(self, path):
2102
"""Fail unless path or paths, which may be abs or relative, exist."""
2103
if not isinstance(path, basestring):
2105
self.failUnlessExists(p)
2107
self.failUnless(osutils.lexists(path),path+" does not exist")
2109
def failIfExists(self, path):
2110
"""Fail if path or paths, which may be abs or relative, exist."""
2111
if not isinstance(path, basestring):
2113
self.failIfExists(p)
2115
self.failIf(osutils.lexists(path),path+" exists")
2117
2113
def assertInWorkingTree(self, path, root_path='.', tree=None):
2118
2114
"""Assert whether path or paths are in the WorkingTree"""
2119
2115
if tree is None:
2308
2316
return TestUtil.TestSuite(result)
2311
def filter_suite_by_re(suite, pattern, exclude_pattern=DEPRECATED_PARAMETER,
2312
random_order=DEPRECATED_PARAMETER):
2319
def filter_suite_by_re(suite, pattern):
2313
2320
"""Create a test suite by filtering another one.
2315
2322
:param suite: the source suite
2316
2323
:param pattern: pattern that names must match
2317
:param exclude_pattern: A pattern that names must not match. This parameter
2318
is deprecated as of bzrlib 1.0. Please use the separate function
2319
exclude_tests_by_re instead.
2320
:param random_order: If True, tests in the new suite will be put in
2321
random order. This parameter is deprecated as of bzrlib 1.0. Please
2322
use the separate function randomize_suite instead.
2323
2324
:returns: the newly created suite
2325
if deprecated_passed(exclude_pattern):
2326
symbol_versioning.warn(
2327
one_zero % "passing exclude_pattern to filter_suite_by_re",
2328
DeprecationWarning, stacklevel=2)
2329
if exclude_pattern is not None:
2330
suite = exclude_tests_by_re(suite, exclude_pattern)
2331
2326
condition = condition_id_re(pattern)
2332
2327
result_suite = filter_suite_by_condition(suite, condition)
2333
if deprecated_passed(random_order):
2334
symbol_versioning.warn(
2335
one_zero % "passing random_order to filter_suite_by_re",
2336
DeprecationWarning, stacklevel=2)
2338
result_suite = randomize_suite(result_suite)
2339
2328
return result_suite
2385
2386
return TestUtil.TestSuite(tests)
2388
@deprecated_function(one_zero)
2389
def sort_suite_by_re(suite, pattern, exclude_pattern=None,
2390
random_order=False, append_rest=True):
2391
"""DEPRECATED: Create a test suite by sorting another one.
2393
This method has been decomposed into separate helper methods that should be
2395
- filter_suite_by_re
2396
- exclude_tests_by_re
2389
def split_suite_by_condition(suite, condition):
2390
"""Split a test suite into two by a condition.
2400
:param suite: the source suite
2401
:param pattern: pattern that names must match in order to go
2402
first in the new suite
2403
:param exclude_pattern: pattern that names must not match, if any
2404
:param random_order: if True, tests in the new suite will be put in
2405
random order (with all tests matching pattern
2407
:param append_rest: if False, pattern is a strict filter and not
2408
just an ordering directive
2409
:returns: the newly created suite
2392
:param suite: The suite to split.
2393
:param condition: The condition to match on. Tests that match this
2394
condition are returned in the first test suite, ones that do not match
2395
are in the second suite.
2396
:return: A tuple of two test suites, where the first contains tests from
2397
suite matching the condition, and the second contains the remainder
2398
from suite. The order within each output suite is the same as it was in
2411
if exclude_pattern is not None:
2412
suite = exclude_tests_by_re(suite, exclude_pattern)
2414
order_changer = randomize_suite
2416
order_changer = preserve_input
2418
suites = map(order_changer, split_suite_by_re(suite, pattern))
2419
return TestUtil.TestSuite(suites)
2421
return order_changer(filter_suite_by_re(suite, pattern))
2403
for test in iter_suite_tests(suite):
2405
matched.append(test)
2407
did_not_match.append(test)
2408
return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
2424
2411
def split_suite_by_re(suite, pattern):
2573
2562
return test_list
2565
def suite_matches_id_list(test_suite, id_list):
2566
"""Warns about tests not appearing or appearing more than once.
2568
:param test_suite: A TestSuite object.
2569
:param test_id_list: The list of test ids that should be found in
2572
:return: (absents, duplicates) absents is a list containing the test found
2573
in id_list but not in test_suite, duplicates is a list containing the
2574
test found multiple times in test_suite.
2576
When using a prefined test id list, it may occurs that some tests do not
2577
exist anymore or that some tests use the same id. This function warns the
2578
tester about potential problems in his workflow (test lists are volatile)
2579
or in the test suite itself (using the same id for several tests does not
2580
help to localize defects).
2582
# Build a dict counting id occurrences
2584
for test in iter_suite_tests(test_suite):
2586
tests[id] = tests.get(id, 0) + 1
2591
occurs = tests.get(id, 0)
2593
not_found.append(id)
2595
duplicates.append(id)
2597
return not_found, duplicates
2576
2600
class TestIdList(object):
2577
2601
"""Test id list to filter a test suite.
2609
2633
modules[mod_name] = True
2610
2634
self.modules = modules
2612
def is_module_name_used(self, module_name):
2636
def refers_to(self, module_name):
2613
2637
"""Is there tests for the module or one of its sub modules."""
2614
2638
return self.modules.has_key(module_name)
2616
def test_in(self, test_id):
2640
def includes(self, test_id):
2617
2641
return self.tests.has_key(test_id)
2620
def test_suite(keep_only=None):
2644
def test_suite(keep_only=None, starting_with=None):
2621
2645
"""Build and return TestSuite for the whole of bzrlib.
2623
2647
:param keep_only: A list of test ids limiting the suite returned.
2649
:param starting_with: An id limiting the suite returned to the tests
2625
2652
This function can be replaced if you need to change the default test
2626
2653
suite on a global basis, but it is not encouraged.
2628
2655
testmod_names = [
2629
2657
'bzrlib.util.tests.test_bencode',
2658
'bzrlib.tests.blackbox',
2659
'bzrlib.tests.branch_implementations',
2660
'bzrlib.tests.bzrdir_implementations',
2661
'bzrlib.tests.commands',
2662
'bzrlib.tests.inventory_implementations',
2663
'bzrlib.tests.interrepository_implementations',
2664
'bzrlib.tests.intertree_implementations',
2665
'bzrlib.tests.interversionedfile_implementations',
2666
'bzrlib.tests.per_lock',
2667
'bzrlib.tests.repository_implementations',
2668
'bzrlib.tests.revisionstore_implementations',
2630
2669
'bzrlib.tests.test__dirstate_helpers',
2631
2670
'bzrlib.tests.test_ancestry',
2632
2671
'bzrlib.tests.test_annotate',
2754
2799
'bzrlib.tests.test_workingtree_4',
2755
2800
'bzrlib.tests.test_wsgi',
2756
2801
'bzrlib.tests.test_xml',
2802
'bzrlib.tests.tree_implementations',
2803
'bzrlib.tests.workingtree_implementations',
2758
test_transport_implementations = [
2759
'bzrlib.tests.test_transport_implementations',
2760
'bzrlib.tests.test_read_bundle',
2762
suite = TestUtil.TestSuite()
2763
2806
loader = TestUtil.TestLoader()
2765
if keep_only is not None:
2808
if starting_with is not None:
2809
# We take precedence over keep_only because *at loading time* using
2810
# both options means we will load less tests for the same final result.
2811
def interesting_module(name):
2813
# Either the module name starts with the specified string
2814
name.startswith(starting_with)
2815
# or it may contain tests starting with the specified string
2816
or starting_with.startswith(name)
2818
loader = TestUtil.FilteredByModuleTestLoader(interesting_module)
2820
elif keep_only is not None:
2766
2821
id_filter = TestIdList(keep_only)
2822
loader = TestUtil.FilteredByModuleTestLoader(id_filter.refers_to)
2823
def interesting_module(name):
2824
return id_filter.refers_to(name)
2827
loader = TestUtil.TestLoader()
2828
def interesting_module(name):
2829
# No filtering, all modules are interesting
2832
suite = loader.suiteClass()
2768
2834
# modules building their suite with loadTestsFromModuleNames
2769
if keep_only is None:
2770
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
2772
for mod in [m for m in testmod_names
2773
if id_filter.is_module_name_used(m)]:
2774
mod_suite = loader.loadTestsFromModuleNames([mod])
2775
mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
2776
suite.addTest(mod_suite)
2778
# modules adapted for transport implementations
2779
from bzrlib.tests.test_transport_implementations import TransportTestProviderAdapter
2780
adapter = TransportTestProviderAdapter()
2781
if keep_only is None:
2782
adapt_modules(test_transport_implementations, adapter, loader, suite)
2784
for mod in [m for m in test_transport_implementations
2785
if id_filter.is_module_name_used(m)]:
2786
mod_suite = TestUtil.TestSuite()
2787
adapt_modules([mod], adapter, loader, mod_suite)
2788
mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
2789
suite.addTest(mod_suite)
2791
# modules defining their own test_suite()
2792
for package in [p for p in packages_to_test()
2793
if (keep_only is None
2794
or id_filter.is_module_name_used(p.__name__))]:
2795
pack_suite = package.test_suite()
2796
if keep_only is not None:
2797
pack_suite = filter_suite_by_id_list(pack_suite, id_filter)
2798
suite.addTest(pack_suite)
2800
# XXX: MODULES_TO_TEST should be obsoleted ?
2801
for mod in [m for m in MODULES_TO_TEST
2802
if keep_only is None or id_filter.is_module_name_used(m)]:
2803
mod_suite = loader.loadTestsFromModule(mod)
2804
if keep_only is not None:
2805
mod_suite = filter_suite_by_id_list(mod_suite, id_filter)
2806
suite.addTest(mod_suite)
2808
for mod in MODULES_TO_DOCTEST:
2835
suite.addTest(loader.loadTestsFromModuleNames(testmod_names))
2837
modules_to_doctest = [
2842
'bzrlib.iterablefile',
2847
'bzrlib.symbol_versioning',
2850
'bzrlib.version_info_formats.format_custom',
2853
for mod in modules_to_doctest:
2854
if not interesting_module(mod):
2855
# No tests to keep here, move along
2810
2858
doc_suite = doctest.DocTestSuite(mod)
2811
2859
except ValueError, e:
2812
2860
print '**failed to get doctest for: %s\n%s' % (mod, e)
2814
if keep_only is not None:
2815
# DocTests may use ids which doesn't contain the module name
2816
doc_suite = filter_suite_by_id_list(doc_suite, id_filter)
2817
2862
suite.addTest(doc_suite)
2819
2864
default_encoding = sys.getdefaultencoding()
2820
for name, plugin in [(n, p) for (n, p) in bzrlib.plugin.plugins().items()
2821
if (keep_only is None
2822
or id_filter.is_module_name_used(
2823
p.module.__name__))]:
2825
plugin_suite = plugin.test_suite()
2826
except ImportError, e:
2827
bzrlib.trace.warning(
2828
'Unable to test plugin "%s": %s', name, e)
2830
if plugin_suite is not None:
2831
if keep_only is not None:
2832
plugin_suite = filter_suite_by_id_list(plugin_suite,
2834
suite.addTest(plugin_suite)
2865
for name, plugin in bzrlib.plugin.plugins().items():
2866
if not interesting_module(plugin.module.__name__):
2868
plugin_suite = plugin.test_suite()
2869
# We used to catch ImportError here and turn it into just a warning,
2870
# but really if you don't have --no-plugins this should be a failure.
2871
# mbp 20080213 - see http://bugs.launchpad.net/bugs/189771
2872
if plugin_suite is None:
2873
plugin_suite = plugin.load_plugin_tests(loader)
2874
if plugin_suite is not None:
2875
suite.addTest(plugin_suite)
2835
2876
if default_encoding != sys.getdefaultencoding():
2836
2877
bzrlib.trace.warning(
2837
2878
'Plugin "%s" tried to reset default encoding to: %s', name,
2838
2879
sys.getdefaultencoding())
2840
2881
sys.setdefaultencoding(default_encoding)
2883
if starting_with is not None:
2884
suite = filter_suite_by_id_startswith(suite, starting_with)
2886
if keep_only is not None:
2887
# Now that the referred modules have loaded their tests, keep only the
2889
suite = filter_suite_by_id_list(suite, id_filter)
2890
# Do some sanity checks on the id_list filtering
2891
not_found, duplicates = suite_matches_id_list(suite, keep_only)
2892
if starting_with is not None:
2893
# The tester has used both keep_only and starting_with, so he is
2894
# already aware that some tests are excluded from the list, there
2895
# is no need to tell him which.
2898
# Some tests mentioned in the list are not in the test suite. The
2899
# list may be out of date, report to the tester.
2900
for id in not_found:
2901
bzrlib.trace.warning('"%s" not found in the test suite', id)
2902
for id in duplicates:
2903
bzrlib.trace.warning('"%s" is used as an id by several tests', id)
2844
def multiply_tests_from_modules(module_name_list, scenario_iter):
2908
def multiply_tests_from_modules(module_name_list, scenario_iter, loader=None):
2845
2909
"""Adapt all tests in some given modules to given scenarios.
2847
2911
This is the recommended public interface for test parameterization.