← Back to team overview

testtools-dev team mailing list archive

[Merge] lp:~lifeless/testtools/load-list into lp:testtools

 

Robert Collins has proposed merging lp:~lifeless/testtools/load-list into lp:testtools.

Requested reviews:
  testtools developers (testtools-dev)


* ``testtools.run`` now supports ``--load-list``, which takes a file containing
  test ids, one per line, and intersects those ids with the tests found. This
  allows fine grained control of what tests are run even when the tests cannot
  be named as objects to import (e.g. due to test parameterisation via
  testscenarios). (Robert Collins)

-- 
https://code.launchpad.net/~lifeless/testtools/load-list/+merge/42196
Your team testtools developers is requested to review the proposed merge of lp:~lifeless/testtools/load-list into lp:testtools.
=== modified file 'NEWS'
--- NEWS	2010-11-29 20:32:00 +0000
+++ NEWS	2010-11-29 23:47:53 +0000
@@ -62,6 +62,12 @@
   them. This is useful for integration with external test analysis/processing
   tools like subunit and testrepository. (Robert Collins)
 
+* ``testtools.run`` now supports ``--load-list``, which takes a file containing
+  test ids, one per line, and intersects those ids with the tests found. This
+  allows fine grained control of what tests are run even when the tests cannot
+  be named as objects to import (e.g. due to test parameterisation via
+  testscenarios). (Robert Collins)
+
 * Update documentation to say how to use testtools.run() on Python 2.4.
   (Jonathan Lange, #501174)
 

=== modified file 'testtools/run.py'
--- testtools/run.py	2010-11-29 20:32:00 +0000
+++ testtools/run.py	2010-11-29 23:47:53 +0000
@@ -62,6 +62,12 @@
 #    removed.
 #  - A tweak has been added to detect 'python -m *.run' and use a
 #    better progName in that case.
+#  - self.module is more comprehensively set to None when being invoked from
+#    the commandline - __name__ is used as a sentinel value.
+#  - --list has been added which can list tests (should be upstreamed).
+#  - --load-list has been added which can reduce the tests used (should be
+#    upstreamed).
+#  - The limitation of using getopt is declared to the user.
 
 FAILFAST     = "  -f, --failfast   Stop on first failure\n"
 CATCHBREAK   = "  -c, --catch      Catch control-C and display results\n"
@@ -75,14 +81,16 @@
   -v, --verbose    Verbose output
   -q, --quiet      Minimal output
   -l, --list       List tests rather than executing them.
+  --load-list      Specifies a file containing test ids, only tests matching
+                   those ids are executed.
 %(failfast)s%(catchbreak)s%(buffer)s
 Examples:
   %(progName)s test_module               - run tests from test_module
   %(progName)s module.TestClass          - run tests from module.TestClass
   %(progName)s module.Class.test_method  - run specified test method
 
-[tests] can be a list of any number of test modules, classes and test
-methods.
+All options must come before [tests].  [tests] can be a list of any number of
+test modules, classes and test methods.
 
 Alternative Usage: %(progName)s discover [options]
 
@@ -93,6 +101,8 @@
   -t directory     Top level directory of project (default to
                    start directory)
   -l, --list       List tests rather than executing them.
+  --load-list      Specifies a file containing test ids, only tests matching
+                   those ids are executed.
 
 For test discovery all test modules must be importable from the top
 level directory of the project.
@@ -130,6 +140,7 @@
         self.buffer = buffer
         self.defaultTest = defaultTest
         self.listtests = False
+        self.load_list = None
         self.testRunner = testRunner
         self.testLoader = testLoader
         progName = argv[0]
@@ -140,6 +151,22 @@
             progName = os.path.basename(argv[0])
         self.progName = progName
         self.parseArgs(argv)
+        if self.load_list:
+            # TODO: preserve existing suites (like testresources does in
+            # OptimisingTestSuite.add, but with a standard protocol).
+            # This is needed because the load_tests hook allows arbitrary
+            # suites, even if that is rarely used.
+            source = file(self.load_list, 'rb')
+            try:
+                lines = source.readlines()
+            finally:
+                source.close()
+            test_ids = set(line.strip() for line in lines)
+            filtered = unittest.TestSuite()
+            for test in iterate_tests(self.test):
+                if test.id() in test_ids:
+                    filtered.addTest(test)
+            self.test = filtered
         if not self.listtests:
             self.runTests()
         else:
@@ -167,7 +194,7 @@
 
         import getopt
         long_opts = ['help', 'verbose', 'quiet', 'failfast', 'catch', 'buffer',
-            'list']
+            'list', 'load-list=']
         try:
             options, args = getopt.getopt(argv[1:], 'hHvqfcbl', long_opts)
             for opt, value in options:
@@ -191,6 +218,8 @@
                     # Should this raise an exception if -b is not valid?
                 if opt in ('-l', '--list'):
                     self.listtests = True
+                if opt == '--load-list':
+                    self.load_list = value
             if len(args) == 0 and self.defaultTest is None:
                 # createTests will load tests from self.module
                 self.testNames = None
@@ -240,6 +269,8 @@
                           help='Top level directory of project (defaults to start directory)')
         parser.add_option('-l', '--list', dest='listtests', default=False,
                           help='List tests rather than running them.')
+        parser.add_option('--load-list', dest='load_list', default=None,
+                          help='Specify a filename containing the test ids to use.')
 
         options, args = parser.parse_args(argv)
         if len(args) > 3:
@@ -257,6 +288,7 @@
         if self.buffer is None:
             self.buffer = options.buffer
         self.listtests = options.listtests
+        self.load_list = options.load_list
 
         if options.verbose:
             self.verbosity = 2

=== modified file 'testtools/tests/test_run.py'
--- testtools/tests/test_run.py	2010-11-29 23:09:22 +0000
+++ testtools/tests/test_run.py	2010-11-29 23:47:53 +0000
@@ -49,6 +49,29 @@
 testtools.runexample.TestFoo.test_quux
 """, out.getvalue())
 
+    def test_run_load_list(self):
+        if fixtures is None:
+            self.skipTest("Need fixtures")
+        package = self.useFixture(SampleTestFixture())
+        out = StringIO.StringIO()
+        # We load two tests - one that exists and one that doesn't, and we
+        # should get the one that exists and neither the one that doesn't nor
+        # the unmentioned one that does.
+        tempdir = self.useFixture(fixtures.TempDir())
+        tempname = tempdir.path + '/tests.list'
+        f = open(tempname, 'wb')
+        try:
+            f.write("""
+testtools.runexample.TestFoo.test_bar
+testtools.runexample.missingtest
+""")
+        finally:
+            f.close()
+        run.main(['prog', '-l', '--load-list', tempname,
+            'testtools.runexample.test_suite'], out)
+        self.assertEqual("""testtools.runexample.TestFoo.test_bar
+""", out.getvalue())
+
 def test_suite():
     from unittest import TestLoader
     return TestLoader().loadTestsFromName(__name__)


Follow ups