~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-12-19 09:10:53 UTC
  • mfrom: (3128.2.2 trunk)
  • Revision ID: pqm@pqm.ubuntu.com-20071219091053-81xgp971m1pgmccf
(robertc) Allow arbitrary parameteriZation of tests cleanly.

Show diffs side-by-side

added added

removed removed

Lines of Context:
78
78
import bzrlib.store
79
79
from bzrlib import symbol_versioning
80
80
from bzrlib.symbol_versioning import (
 
81
    DEPRECATED_PARAMETER,
 
82
    deprecated_function,
81
83
    deprecated_method,
 
84
    deprecated_passed,
82
85
    zero_ninetyone,
83
86
    zero_ninetytwo,
 
87
    one_zero,
84
88
    )
85
89
import bzrlib.trace
86
90
from bzrlib.transport import get_transport
95
99
                          TestSuite,
96
100
                          TestLoader,
97
101
                          )
98
 
from bzrlib.tests.EncodingAdapter import EncodingTestAdapter
99
102
from bzrlib.tests.treeshape import build_tree_contents
100
103
import bzrlib.version_info_formats.format_custom
101
104
from bzrlib.workingtree import WorkingTree, WorkingTreeFormat2
1717
1720
    _TEST_NAME = 'test'
1718
1721
 
1719
1722
    def __init__(self, methodName='runTest'):
1720
 
        # allow test parameterisation after test construction and before test
1721
 
        # execution. Variables that the parameteriser sets need to be 
 
1723
        # allow test parameterization after test construction and before test
 
1724
        # execution. Variables that the parameterizer sets need to be 
1722
1725
        # ones that are not set by setUp, or setUp will trash them.
1723
1726
        super(TestCaseWithMemoryTransport, self).__init__(methodName)
1724
1727
        self.vfs_transport_factory = default_transport
2234
2237
            self.transport_readonly_server = HttpServer
2235
2238
 
2236
2239
 
2237
 
def filter_suite_by_re(suite, pattern, exclude_pattern=None,
2238
 
                       random_order=False):
 
2240
def condition_id_re(pattern):
 
2241
    """Create a condition filter which performs a re check on a test's id.
 
2242
    
 
2243
    :param pattern: A regular expression string.
 
2244
    :return: A callable that returns True if the re matches.
 
2245
    """
 
2246
    filter_re = re.compile(pattern)
 
2247
    def condition(test):
 
2248
        test_id = test.id()
 
2249
        return filter_re.search(test_id)
 
2250
    return condition
 
2251
 
 
2252
 
 
2253
def condition_isinstance(klass_or_klass_list):
 
2254
    """Create a condition filter which returns isinstance(param, klass).
 
2255
    
 
2256
    :return: A callable which when called with one parameter obj return the
 
2257
        result of isinstance(obj, klass_or_klass_list).
 
2258
    """
 
2259
    def condition(obj):
 
2260
        return isinstance(obj, klass_or_klass_list)
 
2261
    return condition
 
2262
 
 
2263
 
 
2264
def exclude_tests_by_condition(suite, condition):
 
2265
    """Create a test suite which excludes some tests from suite.
 
2266
 
 
2267
    :param suite: The suite to get tests from.
 
2268
    :param condition: A callable whose result evaluates True when called with a
 
2269
        test case which should be excluded from the result.
 
2270
    :return: A suite which contains the tests found in suite that fail
 
2271
        condition.
 
2272
    """
 
2273
    result = []
 
2274
    for test in iter_suite_tests(suite):
 
2275
        if not condition(test):
 
2276
            result.append(test)
 
2277
    return TestUtil.TestSuite(result)
 
2278
 
 
2279
 
 
2280
def filter_suite_by_condition(suite, condition):
 
2281
    """Create a test suite by filtering another one.
 
2282
    
 
2283
    :param suite: The source suite.
 
2284
    :param condition: A callable whose result evaluates True when called with a
 
2285
        test case which should be included in the result.
 
2286
    :return: A suite which contains the tests found in suite that pass
 
2287
        condition.
 
2288
    """ 
 
2289
    result = []
 
2290
    for test in iter_suite_tests(suite):
 
2291
        if condition(test):
 
2292
            result.append(test)
 
2293
    return TestUtil.TestSuite(result)
 
2294
 
 
2295
 
 
2296
def filter_suite_by_re(suite, pattern, exclude_pattern=DEPRECATED_PARAMETER,
 
2297
                       random_order=DEPRECATED_PARAMETER):
2239
2298
    """Create a test suite by filtering another one.
2240
2299
    
2241
2300
    :param suite:           the source suite
2242
2301
    :param pattern:         pattern that names must match
2243
 
    :param exclude_pattern: pattern that names must not match, if any
2244
 
    :param random_order:    if True, tests in the new suite will be put in
2245
 
                            random order
 
2302
    :param exclude_pattern: A pattern that names must not match. This parameter
 
2303
        is deprecated as of bzrlib 1.0. Please use the separate function
 
2304
        exclude_tests_by_re instead.
 
2305
    :param random_order:    If True, tests in the new suite will be put in
 
2306
        random order. This parameter is deprecated as of bzrlib 1.0. Please
 
2307
        use the separate function randomize_suite instead.
2246
2308
    :returns: the newly created suite
2247
2309
    """ 
2248
 
    return sort_suite_by_re(suite, pattern, exclude_pattern,
2249
 
        random_order, False)
2250
 
 
2251
 
 
 
2310
    if deprecated_passed(exclude_pattern):
 
2311
        symbol_versioning.warn(
 
2312
            one_zero % "passing exclude_pattern to filter_suite_by_re",
 
2313
                DeprecationWarning, stacklevel=2)
 
2314
        if exclude_pattern is not None:
 
2315
            suite = exclude_tests_by_re(suite, exclude_pattern)
 
2316
    condition = condition_id_re(pattern)
 
2317
    result_suite = filter_suite_by_condition(suite, condition)
 
2318
    if deprecated_passed(random_order):
 
2319
        symbol_versioning.warn(
 
2320
            one_zero % "passing random_order to filter_suite_by_re",
 
2321
                DeprecationWarning, stacklevel=2)
 
2322
        if random_order:
 
2323
            result_suite = randomize_suite(result_suite)
 
2324
    return result_suite
 
2325
 
 
2326
 
 
2327
def exclude_tests_by_re(suite, pattern):
 
2328
    """Create a test suite which excludes some tests from suite.
 
2329
 
 
2330
    :param suite: The suite to get tests from.
 
2331
    :param pattern: A regular expression string. Test ids that match this
 
2332
        pattern will be excluded from the result.
 
2333
    :return: A TestSuite that contains all the tests from suite without the
 
2334
        tests that matched pattern. The order of tests is the same as it was in
 
2335
        suite.
 
2336
    """
 
2337
    return exclude_tests_by_condition(suite, condition_id_re(pattern))
 
2338
 
 
2339
 
 
2340
def preserve_input(something):
 
2341
    """A helper for performing test suite transformation chains.
 
2342
 
 
2343
    :param something: Anything you want to preserve.
 
2344
    :return: Something.
 
2345
    """
 
2346
    return something
 
2347
 
 
2348
 
 
2349
def randomize_suite(suite):
 
2350
    """Return a new TestSuite with suite's tests in random order.
 
2351
    
 
2352
    The tests in the input suite are flattened into a single suite in order to
 
2353
    accomplish this. Any nested TestSuites are removed to provide global
 
2354
    randomness.
 
2355
    """
 
2356
    tests = list(iter_suite_tests(suite))
 
2357
    random.shuffle(tests)
 
2358
    return TestUtil.TestSuite(tests)
 
2359
 
 
2360
 
 
2361
@deprecated_function(one_zero)
2252
2362
def sort_suite_by_re(suite, pattern, exclude_pattern=None,
2253
2363
                     random_order=False, append_rest=True):
2254
 
    """Create a test suite by sorting another one.
 
2364
    """DEPRECATED: Create a test suite by sorting another one.
 
2365
 
 
2366
    This method has been decomposed into separate helper methods that should be
 
2367
    called directly:
 
2368
     - filter_suite_by_re
 
2369
     - exclude_tests_by_re
 
2370
     - randomize_suite
 
2371
     - split_suite_by_re
2255
2372
    
2256
2373
    :param suite:           the source suite
2257
2374
    :param pattern:         pattern that names must match in order to go
2258
2375
                            first in the new suite
2259
2376
    :param exclude_pattern: pattern that names must not match, if any
2260
2377
    :param random_order:    if True, tests in the new suite will be put in
2261
 
                            random order
 
2378
                            random order (with all tests matching pattern
 
2379
                            first).
2262
2380
    :param append_rest:     if False, pattern is a strict filter and not
2263
2381
                            just an ordering directive
2264
2382
    :returns: the newly created suite
2265
2383
    """ 
2266
 
    first = []
2267
 
    second = []
 
2384
    if exclude_pattern is not None:
 
2385
        suite = exclude_tests_by_re(suite, exclude_pattern)
 
2386
    if random_order:
 
2387
        order_changer = randomize_suite
 
2388
    else:
 
2389
        order_changer = preserve_input
 
2390
    if append_rest:
 
2391
        suites = map(order_changer, split_suite_by_re(suite, pattern))
 
2392
        return TestUtil.TestSuite(suites)
 
2393
    else:
 
2394
        return order_changer(filter_suite_by_re(suite, pattern))
 
2395
 
 
2396
 
 
2397
def split_suite_by_re(suite, pattern):
 
2398
    """Split a test suite into two by a regular expression.
 
2399
    
 
2400
    :param suite: The suite to split.
 
2401
    :param pattern: A regular expression string. Test ids that match this
 
2402
        pattern will be in the first test suite returned, and the others in the
 
2403
        second test suite returned.
 
2404
    :return: A tuple of two test suites, where the first contains tests from
 
2405
        suite matching pattern, and the second contains the remainder from
 
2406
        suite. The order within each output suite is the same as it was in
 
2407
        suite.
 
2408
    """ 
 
2409
    matched = []
 
2410
    did_not_match = []
2268
2411
    filter_re = re.compile(pattern)
2269
 
    if exclude_pattern is not None:
2270
 
        exclude_re = re.compile(exclude_pattern)
2271
2412
    for test in iter_suite_tests(suite):
2272
2413
        test_id = test.id()
2273
 
        if exclude_pattern is None or not exclude_re.search(test_id):
2274
 
            if filter_re.search(test_id):
2275
 
                first.append(test)
2276
 
            elif append_rest:
2277
 
                second.append(test)
2278
 
    if random_order:
2279
 
        random.shuffle(first)
2280
 
        random.shuffle(second)
2281
 
    return TestUtil.TestSuite(first + second)
 
2414
        if filter_re.search(test_id):
 
2415
            matched.append(test)
 
2416
        else:
 
2417
            did_not_match.append(test)
 
2418
    return TestUtil.TestSuite(matched), TestUtil.TestSuite(did_not_match)
2282
2419
 
2283
2420
 
2284
2421
def run_suite(suite, name='test', verbose=False, pattern=".*",
2320
2457
            (random_seed))
2321
2458
        random.seed(random_seed)
2322
2459
    # Customise the list of tests if requested
2323
 
    if pattern != '.*' or exclude_pattern is not None or random_order:
 
2460
    if exclude_pattern is not None:
 
2461
        suite = exclude_tests_by_re(suite, exclude_pattern)
 
2462
    if random_order:
 
2463
        order_changer = randomize_suite
 
2464
    else:
 
2465
        order_changer = preserve_input
 
2466
    if pattern != '.*' or random_order:
2324
2467
        if matching_tests_first:
2325
 
            suite = sort_suite_by_re(suite, pattern, exclude_pattern,
2326
 
                random_order)
 
2468
            suites = map(order_changer, split_suite_by_re(suite, pattern))
 
2469
            suite = TestUtil.TestSuite(suites)
2327
2470
        else:
2328
 
            suite = filter_suite_by_re(suite, pattern, exclude_pattern,
2329
 
                random_order)
 
2471
            suite = order_changer(filter_suite_by_re(suite, pattern))
2330
2472
 
 
2473
    # Activate code coverage.
2331
2474
    if coverage_dir is not None:
2332
2475
        tracer = trace.Trace(count=1, trace=0)
2333
2476
        sys.settrace(tracer.globaltrace)
2534
2677
    from bzrlib.tests.test_transport_implementations import TransportTestProviderAdapter
2535
2678
    adapter = TransportTestProviderAdapter()
2536
2679
    adapt_modules(test_transport_implementations, adapter, loader, suite)
2537
 
    adapt_tests(
2538
 
        ["bzrlib.tests.test_msgeditor.MsgEditorTest."
2539
 
         "test__create_temp_file_with_commit_template_in_unicode_dir"],
2540
 
        EncodingTestAdapter(), loader, suite)
2541
2680
    for package in packages_to_test():
2542
2681
        suite.addTest(package.test_suite())
2543
2682
    for m in MODULES_TO_TEST: