Rev 2448: (Ian Clatworthy) Bugs #102679, #102686. Add --exclude and --randomize to 'bzr selftest' in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Tue Apr 24 04:12:10 BST 2007


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 2448
revision-id: pqm at pqm.ubuntu.com-20070424031208-9y04a1j0yx3fjte5
parent: pqm at pqm.ubuntu.com-20070423170758-qd512ltqglzfo6w9
parent: john at arbash-meinel.com-20070424024356-nffcxmkfaigudmrp
committer: Canonical.com Patch Queue Manager<pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Tue 2007-04-24 04:12:08 +0100
message:
  (Ian Clatworthy) Bugs #102679, #102686. Add --exclude and --randomize to 'bzr selftest'
modified:
  HACKING                        HACKING-20050805200004-2a5dc975d870f78c
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
  bzrlib/commands.py             bzr.py-20050309040720-d10f4714595cf8c3
  bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
  bzrlib/tests/blackbox/test_selftest.py test_selftest.py-20060123024542-01c5f1bbcb596d78
  bzrlib/tests/test_selftest.py  test_selftest.py-20051202044319-c110a115d8c0456a
    ------------------------------------------------------------
    revno: 2418.4.2
    merged: john at arbash-meinel.com-20070424024356-nffcxmkfaigudmrp
    parent: john at arbash-meinel.com-20070413201949-ay6r5nh3bgsxfogw
    parent: pqm at pqm.ubuntu.com-20070423170758-qd512ltqglzfo6w9
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: jam-integration
    timestamp: Mon 2007-04-23 21:43:56 -0500
    message:
      [merge] bzr.dev 2447
    ------------------------------------------------------------
    revno: 2418.4.1
    merged: john at arbash-meinel.com-20070413201949-ay6r5nh3bgsxfogw
    parent: pqm at pqm.ubuntu.com-20070413174100-zpfqleaf5ph9ycx4
    parent: ian.clatworthy at internode.on.net-20070413004631-nkdsnpcuy8xb0x62
    committer: John Arbash Meinel <john at arbash-meinel.com>
    branch nick: jam-integration
    timestamp: Fri 2007-04-13 15:19:49 -0500
    message:
      (Ian Clatworthy) Bugs #102679, #102686. Add --exclude and --randomize to 'bzr selftest'
    ------------------------------------------------------------
    revno: 2394.2.10
    merged: ian.clatworthy at internode.on.net-20070413004631-nkdsnpcuy8xb0x62
    parent: ian.clatworthy at internode.on.net-20070413004053-y5wr76o3512rjawk
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.selftest-not
    timestamp: Fri 2007-04-13 10:46:31 +1000
    message:
      another doc fix and whitespace fixes
    ------------------------------------------------------------
    revno: 2394.2.9
    merged: ian.clatworthy at internode.on.net-20070413004053-y5wr76o3512rjawk
    parent: ian.clatworthy at internode.on.net-20070413003033-k3nc1zq02qlkb8cj
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.selftest-not
    timestamp: Fri 2007-04-13 10:40:53 +1000
    message:
      update NEWS and help to reflect removal of comma support
    ------------------------------------------------------------
    revno: 2394.2.8
    merged: ian.clatworthy at internode.on.net-20070413003033-k3nc1zq02qlkb8cj
    parent: ian.clatworthy at internode.on.net-20070411021409-im2b7jkohfnb5boq
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.selftest-not
    timestamp: Fri 2007-04-13 10:30:33 +1000
    message:
      incorporate feedback from jam
    ------------------------------------------------------------
    revno: 2394.2.7
    merged: ian.clatworthy at internode.on.net-20070411021409-im2b7jkohfnb5boq
    parent: ian.clatworthy at internode.on.net-20070410142343-6bfz9k67b8tvrz6x
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.selftest-not
    timestamp: Wed 2007-04-11 12:14:09 +1000
    message:
      Added whitebox tests - filter_suite_by_re and sort_suite_by_re
    ------------------------------------------------------------
    revno: 2394.2.6
    merged: ian.clatworthy at internode.on.net-20070410142343-6bfz9k67b8tvrz6x
    parent: ian.clatworthy at internode.on.net-20070410090806-d9pkgwomcpbkizj2
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.selftest-not
    timestamp: Wed 2007-04-11 00:23:43 +1000
    message:
      completed blackbox tests
    ------------------------------------------------------------
    revno: 2394.2.5
    merged: ian.clatworthy at internode.on.net-20070410090806-d9pkgwomcpbkizj2
    parent: ian.clatworthy at internode.on.net-20070404131351-xqdiyfvwohs96ecs
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.selftest-not
    timestamp: Tue 2007-04-10 19:08:06 +1000
    message:
      list-only working, include test not
    ------------------------------------------------------------
    revno: 2394.2.4
    merged: ian.clatworthy at internode.on.net-20070404131351-xqdiyfvwohs96ecs
    parent: ian.clatworthy at internode.on.net-20070404131147-r9dp5hu8166xhb8u
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.selftest-not
    timestamp: Wed 2007-04-04 23:13:51 +1000
    message:
      Clean up whitespace
    ------------------------------------------------------------
    revno: 2394.2.3
    merged: ian.clatworthy at internode.on.net-20070404131147-r9dp5hu8166xhb8u
    parent: ian.clatworthy at internode.on.net-20070404125915-w0m76xc9tjxhbo42
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.selftest-not
    timestamp: Wed 2007-04-04 23:11:47 +1000
    message:
      Backed out test junk
    ------------------------------------------------------------
    revno: 2394.2.2
    merged: ian.clatworthy at internode.on.net-20070404125915-w0m76xc9tjxhbo42
    parent: ian.clatworthy at internode.on.net-20070404091010-1j1sdngh8t77ef9v
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.selftest-not
    timestamp: Wed 2007-04-04 22:59:15 +1000
    message:
      Add --randomize and update help
    ------------------------------------------------------------
    revno: 2394.2.1
    merged: ian.clatworthy at internode.on.net-20070404091010-1j1sdngh8t77ef9v
    parent: pqm at pqm.ubuntu.com-20070404005411-46c388fbf2acf940
    committer: Ian Clatworthy <ian.clatworthy at internode.on.net>
    branch nick: bzr.selftest-not
    timestamp: Wed 2007-04-04 19:10:10 +1000
    message:
      --list and --exclude first cut
=== modified file 'HACKING'
--- a/HACKING	2007-04-23 02:29:35 +0000
+++ b/HACKING	2007-04-24 02:43:56 +0000
@@ -442,10 +442,17 @@
 
   ./bzr selftest -v blackbox
 
-To skip a particular test (or set of tests), you need to use a negative
-match, like so::
-
-  ./bzr selftest '^(?!.*blackbox)'  
+To skip a particular test (or set of tests), use the --exclude option
+(shorthand -x) like so::
+
+  ./bzr selftest -v -x blackbox  
+
+To list tests without running them, use the --list-only option like so::
+
+  ./bzr selftest --list-only
+
+This option can be combined with other selftest options (like -x) and
+filter patterns to understand their effect.
 
 
 Errors and exceptions

=== modified file 'NEWS'
--- a/NEWS	2007-04-23 07:50:15 +0000
+++ b/NEWS	2007-04-24 02:43:56 +0000
@@ -5,6 +5,17 @@
     * Merge directives can now be supplied as input to `merge` and `pull`,
       like bundles can.  (Aaron Bentley)
 
+    * selftest now supports --list-only to list tests instead of running
+      them. (Ian Clatworthy)
+
+    * selftest now supports --exclude PATTERN (or -x PATTERN) to exclude
+      tests with names that match that regular expression.
+      (Ian Clatworthy, #102679)
+
+    * selftest now supports --randomize SEED to run tests in a random order.
+      SEED is typically the value 'now' meaning 'use the current time'.
+      (Ian Clatworthy, #102686)
+
     * New option ``--fixes`` to commit, which stores bug fixing annotations as
       revision properties. Built-in support for Launchpad, Debian, Trac and
       Bugzilla bug trackers. (Jonathan Lange, James Henstridge, Robert Collins)

=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2007-04-23 07:50:15 +0000
+++ b/bzrlib/builtins.py	2007-04-24 02:43:56 +0000
@@ -2326,7 +2326,7 @@
 class cmd_selftest(Command):
     """Run internal test suite.
     
-    This creates temporary test directories in the working directory, but not
+    This creates temporary test directories in the working directory, but no
     existing data is affected.  These directories are deleted if the tests
     pass, or left behind to help in debugging if they fail and --keep-output
     is specified.
@@ -2339,6 +2339,21 @@
     all other tests are run.  This is useful if you have been working in a
     particular area, but want to make sure nothing else was broken.
 
+    If --exclude is given, tests that match that regular expression are
+    excluded, regardless of whether they match --first or not.
+
+    To help catch accidential dependencies between tests, the --randomize
+    option is useful. In most cases, the argument used is the word 'now'.
+    Note that the seed used for the random number generator is displayed
+    when this option is used. The seed can be explicitly passed as the
+    argument to this option if required. This enables reproduction of the
+    actual ordering used if and when an order sensitive problem is encountered.
+
+    If --list-only is given, the tests that would be run are listed. This is
+    useful when combined with --first, --exclude and/or --randomize to
+    understand their impact. The test harness reports "Listed nn tests in ..."
+    instead of "Ran nn tests in ..." when list mode is enabled.
+
     If the global option '--no-plugins' is given, plugins are not loaded
     before running the selftests.  This has two effects: features provided or
     modified by plugins will not be tested, and tests provided by plugins will
@@ -2357,8 +2372,6 @@
     of running tests to create such subdirectories. This is default behavior
     on Windows because of path length limitation.
     """
-    # TODO: --list should give a list of all available tests
-
     # NB: this is used from the class without creating an instance, which is
     # why it does not have a self parameter.
     def get_transport_type(typestring):
@@ -2405,13 +2418,23 @@
                             ),
                      Option('numbered-dirs',
                             help='use numbered dirs for TestCaseInTempDir'),
+                     Option('list-only',
+                            help='list the tests instead of running them'),
+                     Option('randomize', type=str, argname="SEED",
+                            help='randomize the order of tests using the given'
+                                 ' seed or "now" for the current time'),
+                     Option('exclude', type=str, argname="PATTERN",
+                            short_name='x',
+                            help='exclude tests that match this regular'
+                                 ' expression'),
                      ]
     encoding_type = 'replace'
 
     def run(self, testspecs_list=None, verbose=None, one=False,
             keep_output=False, transport=None, benchmark=None,
             lsprof_timed=None, cache_dir=None, clean_output=False,
-            first=False, numbered_dirs=None):
+            first=False, numbered_dirs=None, list_only=False,
+            randomize=None, exclude=None):
         import bzrlib.ui
         from bzrlib.tests import selftest
         import bzrlib.benchmarks as benchmarks
@@ -2456,6 +2479,9 @@
                               bench_history=benchfile,
                               matching_tests_first=first,
                               numbered_dirs=numbered_dirs,
+                              list_only=list_only,
+                              random_seed=randomize,
+                              exclude_pattern=exclude
                               )
         finally:
             if benchfile is not None:

=== modified file 'bzrlib/commands.py'
--- a/bzrlib/commands.py	2007-04-23 00:28:58 +0000
+++ b/bzrlib/commands.py	2007-04-24 02:43:56 +0000
@@ -714,9 +714,11 @@
 
 def run_bzr_catch_errors(argv):
     try:
-        return run_bzr(argv)
-        # do this here inside the exception wrappers to catch EPIPE
-        sys.stdout.flush()
+        try:
+            return run_bzr(argv)
+        finally:
+            # do this here inside the exception wrappers to catch EPIPE
+            sys.stdout.flush()
     except (KeyboardInterrupt, Exception), e:
         # used to handle AssertionError and KeyboardInterrupt
         # specially here, but hopefully they're handled ok by the logger now

=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py	2007-04-23 06:55:58 +0000
+++ b/bzrlib/tests/__init__.py	2007-04-24 02:43:56 +0000
@@ -34,6 +34,7 @@
 import logging
 import os
 from pprint import pformat
+import random
 import re
 import shlex
 import stat
@@ -501,6 +502,7 @@
                  keep_output=False,
                  bench_history=None,
                  use_numbered_dirs=False,
+                 list_only=False
                  ):
         self.stream = unittest._WritelnDecorator(stream)
         self.descriptions = descriptions
@@ -508,6 +510,7 @@
         self.keep_output = keep_output
         self._bench_history = bench_history
         self.use_numbered_dirs = use_numbered_dirs
+        self.list_only = list_only
 
     def run(self, test):
         "Run the given test case or test suite."
@@ -525,14 +528,24 @@
                               )
         result.stop_early = self.stop_on_failure
         result.report_starting()
-        test.run(result)
+        if self.list_only:
+            if self.verbosity >= 2:
+                self.stream.writeln("Listing tests only ...\n")
+            run = 0
+            for t in iter_suite_tests(test):
+                self.stream.writeln("%s" % (t.id()))
+                run += 1
+            actionTaken = "Listed"
+        else: 
+            test.run(result)
+            run = result.testsRun
+            actionTaken = "Ran"
         stopTime = time.time()
         timeTaken = stopTime - startTime
         result.printErrors()
         self.stream.writeln(result.separator2)
-        run = result.testsRun
-        self.stream.writeln("Ran %d test%s in %.3fs" %
-                            (run, run != 1 and "s" or "", timeTaken))
+        self.stream.writeln("%s %d test%s in %.3fs" % (actionTaken,
+                            run, run != 1 and "s" or "", timeTaken))
         self.stream.writeln()
         if not result.wasSuccessful():
             self.stream.write("FAILED (")
@@ -2053,24 +2066,50 @@
             self.transport_readonly_server = HttpServer
 
 
-def filter_suite_by_re(suite, pattern):
-    result = TestUtil.TestSuite()
-    filter_re = re.compile(pattern)
-    for test in iter_suite_tests(suite):
-        if filter_re.search(test.id()):
-            result.addTest(test)
-    return result
-
-
-def sort_suite_by_re(suite, pattern):
+def filter_suite_by_re(suite, pattern, exclude_pattern=None,
+                       random_order=False):
+    """Create a test suite by filtering another one.
+    
+    :param suite:           the source suite
+    :param pattern:         pattern that names must match
+    :param exclude_pattern: pattern that names must not match, if any
+    :param random_order:    if True, tests in the new suite will be put in
+                            random order
+    :returns: the newly created suite
+    """ 
+    return sort_suite_by_re(suite, pattern, exclude_pattern,
+        random_order, False)
+
+
+def sort_suite_by_re(suite, pattern, exclude_pattern=None,
+                     random_order=False, append_rest=True):
+    """Create a test suite by sorting another one.
+    
+    :param suite:           the source suite
+    :param pattern:         pattern that names must match in order to go
+                            first in the new suite
+    :param exclude_pattern: pattern that names must not match, if any
+    :param random_order:    if True, tests in the new suite will be put in
+                            random order
+    :param append_rest:     if False, pattern is a strict filter and not
+                            just an ordering directive
+    :returns: the newly created suite
+    """ 
     first = []
     second = []
     filter_re = re.compile(pattern)
+    if exclude_pattern is not None:
+        exclude_re = re.compile(exclude_pattern)
     for test in iter_suite_tests(suite):
-        if filter_re.search(test.id()):
-            first.append(test)
-        else:
-            second.append(test)
+        test_id = test.id()
+        if exclude_pattern is None or not exclude_re.search(test_id):
+            if filter_re.search(test_id):
+                first.append(test)
+            elif append_rest:
+                second.append(test)
+    if random_order:
+        random.shuffle(first)
+        random.shuffle(second)
     return TestUtil.TestSuite(first + second)
 
 
@@ -2078,7 +2117,11 @@
               stop_on_failure=False, keep_output=False,
               transport=None, lsprof_timed=None, bench_history=None,
               matching_tests_first=None,
-              numbered_dirs=None):
+              numbered_dirs=None,
+              list_only=False,
+              random_seed=None,
+              exclude_pattern=None,
+              ):
     use_numbered_dirs = bool(numbered_dirs)
 
     TestCase._gather_lsprof_in_benchmarks = lsprof_timed
@@ -2094,13 +2137,33 @@
                             keep_output=keep_output,
                             bench_history=bench_history,
                             use_numbered_dirs=use_numbered_dirs,
+                            list_only=list_only,
                             )
     runner.stop_on_failure=stop_on_failure
-    if pattern != '.*':
+    # Initialise the random number generator and display the seed used.
+    # We convert the seed to a long to make it reuseable across invocations.
+    random_order = False
+    if random_seed is not None:
+        random_order = True
+        if random_seed == "now":
+            random_seed = long(time.time())
+        else:
+            # Convert the seed to a long if we can
+            try:
+                random_seed = long(random_seed)
+            except:
+                pass
+        runner.stream.writeln("Randomizing test order using seed %s\n" %
+            (random_seed))
+        random.seed(random_seed)
+    # Customise the list of tests if requested
+    if pattern != '.*' or exclude_pattern is not None or random_order:
         if matching_tests_first:
-            suite = sort_suite_by_re(suite, pattern)
+            suite = sort_suite_by_re(suite, pattern, exclude_pattern,
+                random_order)
         else:
-            suite = filter_suite_by_re(suite, pattern)
+            suite = filter_suite_by_re(suite, pattern, exclude_pattern,
+                random_order)
     result = runner.run(suite)
     return result.wasSuccessful()
 
@@ -2112,7 +2175,10 @@
              lsprof_timed=None,
              bench_history=None,
              matching_tests_first=None,
-             numbered_dirs=None):
+             numbered_dirs=None,
+             list_only=False,
+             random_seed=None,
+             exclude_pattern=None):
     """Run the whole test suite under the enhanced runner"""
     # XXX: Very ugly way to do this...
     # Disable warning about old formats because we don't want it to disturb
@@ -2136,7 +2202,10 @@
                      lsprof_timed=lsprof_timed,
                      bench_history=bench_history,
                      matching_tests_first=matching_tests_first,
-                     numbered_dirs=numbered_dirs)
+                     numbered_dirs=numbered_dirs,
+                     list_only=list_only,
+                     random_seed=random_seed,
+                     exclude_pattern=exclude_pattern)
     finally:
         default_transport = old_transport
 

=== modified file 'bzrlib/tests/blackbox/test_selftest.py'
--- a/bzrlib/tests/blackbox/test_selftest.py	2007-03-08 22:08:08 +0000
+++ b/bzrlib/tests/blackbox/test_selftest.py	2007-04-13 00:30:33 +0000
@@ -17,6 +17,7 @@
 """UI tests for the test framework."""
 
 import os
+import re
 import signal
 import sys
 
@@ -491,3 +492,85 @@
         self.assertEquals(['bzr','bzrlib','setup.py',
                            'test9999.tmp','tests'],
                            after)
+
+
+class TestSelftestListOnly(TestCase):
+
+    @staticmethod
+    def _parse_test_list(lines, newlines_in_header=1):
+        "Parse a list of lines into a tuple of 3 lists (header,body,footer)."
+
+        in_header = True
+        in_footer = False
+        header = []
+        body = []
+        footer = []
+        header_newlines_found = 0 
+        for line in lines:
+            if in_header:
+                if line == '':
+                    header_newlines_found += 1
+                    if header_newlines_found >= newlines_in_header:
+                        in_header = False
+                        continue
+                header.append(line)
+            elif not in_footer:
+                if line.startswith('-------'):
+                    in_footer = True
+                else:
+                    body.append(line)
+            else:
+                footer.append(line)
+        # If the last body line is blank, drop it off the list
+        if len(body) > 0 and body[-1] == '':
+            body.pop()                
+        return (header,body,footer)
+
+    def test_list_only(self):
+        # check that bzr selftest --list-only works correctly
+        out,err = self.run_bzr_captured(['selftest', 'selftest',
+            '--list-only'])
+        self.assertEndsWith(err, 'tests passed\n')
+        (header,body,footer) = self._parse_test_list(out.splitlines())
+        num_tests = len(body)
+        self.assertContainsRe(footer[0], 'Listed %s tests in' % num_tests)
+
+    def test_list_only_filtered(self):
+        # check that a filtered --list-only works, both include and exclude
+        out_all,err_all = self.run_bzr_captured(['selftest', '--list-only'])
+        tests_all = self._parse_test_list(out_all.splitlines())[1]
+        out_incl,err_incl = self.run_bzr_captured(['selftest', '--list-only',
+          'selftest'])
+        tests_incl = self._parse_test_list(out_incl.splitlines())[1]
+        self.assertSubset(tests_incl, tests_all)
+        out_excl,err_excl = self.run_bzr_captured(['selftest', '--list-only',
+          '--exclude', 'selftest'])
+        tests_excl = self._parse_test_list(out_excl.splitlines())[1]
+        self.assertSubset(tests_excl, tests_all)
+        set_incl = set(tests_incl)
+        set_excl = set(tests_excl)
+        intersection = set_incl.intersection(set_excl)
+        self.assertEquals(0, len(intersection))
+        self.assertEquals(len(tests_all), len(tests_incl) + len(tests_excl))
+
+    def test_list_only_random(self):
+        # check that --randomize works correctly
+        out_all,err_all = self.run_bzr_captured(['selftest', '--list-only',
+            'selftest'])
+        tests_all = self._parse_test_list(out_all.splitlines())[1]
+        out_rand,err_rand = self.run_bzr_captured(['selftest', '--list-only',
+            'selftest', '--randomize', 'now'])
+        (header_rand,tests_rand,dummy) = self._parse_test_list(
+            out_rand.splitlines(), 2)
+        self.assertNotEqual(tests_all, tests_rand)
+        self.assertEqual(sorted(tests_all), sorted(tests_rand))
+        # Check that the seed can be reused to get the exact same order
+        seed_re = re.compile('Randomizing test order using seed (\w+)')
+        match_obj = seed_re.search(header_rand[-1])
+        seed = match_obj.group(1)
+        out_rand2,err_rand2 = self.run_bzr_captured(['selftest', '--list-only',
+            'selftest', '--randomize', seed])
+        (header_rand2,tests_rand2,dummy) = self._parse_test_list(
+            out_rand2.splitlines(), 2)
+        self.assertEqual(tests_rand, tests_rand2)
+

=== modified file 'bzrlib/tests/test_selftest.py'
--- a/bzrlib/tests/test_selftest.py	2007-04-20 03:00:57 +0000
+++ b/bzrlib/tests/test_selftest.py	2007-04-24 02:43:56 +0000
@@ -47,9 +47,14 @@
                           TestCaseWithTransport,
                           TestSkipped,
                           TestSuite,
+                          TestUtil,
                           TextTestRunner,
                           UnavailableFeature,
                           clean_selftest_output,
+                          iter_suite_tests,
+                          filter_suite_by_re,
+                          sort_suite_by_re,
+                          test_suite
                           )
 from bzrlib.tests.test_sftp_transport import TestCaseWithSFTPServer
 from bzrlib.tests.TestUtil import _load_module_by_name
@@ -1506,3 +1511,27 @@
         feature = Feature()
         exception = UnavailableFeature(feature)
         self.assertIs(feature, exception.args[0])
+
+
+class TestSelftestFiltering(TestCase):
+
+    def setUp(self):
+        self.suite = TestUtil.TestSuite()
+        self.loader = TestUtil.TestLoader()
+        self.suite.addTest(self.loader.loadTestsFromModuleNames([
+            'bzrlib.tests.test_selftest']))
+        self.all_names = [t.id() for t in iter_suite_tests(self.suite)]
+
+    def test_filter_suite_by_re(self):
+        filtered_suite = filter_suite_by_re(self.suite, 'test_filter')
+        filtered_names = [t.id() for t in iter_suite_tests(filtered_suite)]
+        self.assertEqual(filtered_names, ['bzrlib.tests.test_selftest.'
+            'TestSelftestFiltering.test_filter_suite_by_re'])
+            
+    def test_sort_suite_by_re(self):
+        sorted_suite = sort_suite_by_re(self.suite, 'test_filter')
+        sorted_names = [t.id() for t in iter_suite_tests(sorted_suite)]
+        self.assertEqual(sorted_names[0], 'bzrlib.tests.test_selftest.'
+            'TestSelftestFiltering.test_filter_suite_by_re')
+        self.assertEquals(sorted(self.all_names), sorted(sorted_names))
+




More information about the bazaar-commits mailing list