Merge lp:~lifeless/testtools/load-list into lp:~testtools-committers/testtools/trunk

Proposed by Robert Collins
Status: Merged
Merged at revision: 146
Proposed branch: lp:~lifeless/testtools/load-list
Merge into: lp:~testtools-committers/testtools/trunk
Diff against target: 161 lines (+64/-3)
3 files modified
NEWS (+6/-0)
testtools/run.py (+35/-3)
testtools/tests/test_run.py (+23/-0)
To merge this branch: bzr merge lp:~lifeless/testtools/load-list
Reviewer Review Type Date Requested Status
testtools developers Pending
Review via email: mp+42196@code.launchpad.net

Description of the change

* ``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)

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'NEWS'
--- NEWS 2010-11-29 20:32:00 +0000
+++ NEWS 2010-11-29 23:47:53 +0000
@@ -62,6 +62,12 @@
62 them. This is useful for integration with external test analysis/processing62 them. This is useful for integration with external test analysis/processing
63 tools like subunit and testrepository. (Robert Collins)63 tools like subunit and testrepository. (Robert Collins)
6464
65* ``testtools.run`` now supports ``--load-list``, which takes a file containing
66 test ids, one per line, and intersects those ids with the tests found. This
67 allows fine grained control of what tests are run even when the tests cannot
68 be named as objects to import (e.g. due to test parameterisation via
69 testscenarios). (Robert Collins)
70
65* Update documentation to say how to use testtools.run() on Python 2.4.71* Update documentation to say how to use testtools.run() on Python 2.4.
66 (Jonathan Lange, #501174)72 (Jonathan Lange, #501174)
6773
6874
=== 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 @@
62# removed.62# removed.
63# - A tweak has been added to detect 'python -m *.run' and use a63# - A tweak has been added to detect 'python -m *.run' and use a
64# better progName in that case.64# better progName in that case.
65# - self.module is more comprehensively set to None when being invoked from
66# the commandline - __name__ is used as a sentinel value.
67# - --list has been added which can list tests (should be upstreamed).
68# - --load-list has been added which can reduce the tests used (should be
69# upstreamed).
70# - The limitation of using getopt is declared to the user.
6571
66FAILFAST = " -f, --failfast Stop on first failure\n"72FAILFAST = " -f, --failfast Stop on first failure\n"
67CATCHBREAK = " -c, --catch Catch control-C and display results\n"73CATCHBREAK = " -c, --catch Catch control-C and display results\n"
@@ -75,14 +81,16 @@
75 -v, --verbose Verbose output81 -v, --verbose Verbose output
76 -q, --quiet Minimal output82 -q, --quiet Minimal output
77 -l, --list List tests rather than executing them.83 -l, --list List tests rather than executing them.
84 --load-list Specifies a file containing test ids, only tests matching
85 those ids are executed.
78%(failfast)s%(catchbreak)s%(buffer)s86%(failfast)s%(catchbreak)s%(buffer)s
79Examples:87Examples:
80 %(progName)s test_module - run tests from test_module88 %(progName)s test_module - run tests from test_module
81 %(progName)s module.TestClass - run tests from module.TestClass89 %(progName)s module.TestClass - run tests from module.TestClass
82 %(progName)s module.Class.test_method - run specified test method90 %(progName)s module.Class.test_method - run specified test method
8391
84[tests] can be a list of any number of test modules, classes and test92All options must come before [tests]. [tests] can be a list of any number of
85methods.93test modules, classes and test methods.
8694
87Alternative Usage: %(progName)s discover [options]95Alternative Usage: %(progName)s discover [options]
8896
@@ -93,6 +101,8 @@
93 -t directory Top level directory of project (default to101 -t directory Top level directory of project (default to
94 start directory)102 start directory)
95 -l, --list List tests rather than executing them.103 -l, --list List tests rather than executing them.
104 --load-list Specifies a file containing test ids, only tests matching
105 those ids are executed.
96106
97For test discovery all test modules must be importable from the top107For test discovery all test modules must be importable from the top
98level directory of the project.108level directory of the project.
@@ -130,6 +140,7 @@
130 self.buffer = buffer140 self.buffer = buffer
131 self.defaultTest = defaultTest141 self.defaultTest = defaultTest
132 self.listtests = False142 self.listtests = False
143 self.load_list = None
133 self.testRunner = testRunner144 self.testRunner = testRunner
134 self.testLoader = testLoader145 self.testLoader = testLoader
135 progName = argv[0]146 progName = argv[0]
@@ -140,6 +151,22 @@
140 progName = os.path.basename(argv[0])151 progName = os.path.basename(argv[0])
141 self.progName = progName152 self.progName = progName
142 self.parseArgs(argv)153 self.parseArgs(argv)
154 if self.load_list:
155 # TODO: preserve existing suites (like testresources does in
156 # OptimisingTestSuite.add, but with a standard protocol).
157 # This is needed because the load_tests hook allows arbitrary
158 # suites, even if that is rarely used.
159 source = file(self.load_list, 'rb')
160 try:
161 lines = source.readlines()
162 finally:
163 source.close()
164 test_ids = set(line.strip() for line in lines)
165 filtered = unittest.TestSuite()
166 for test in iterate_tests(self.test):
167 if test.id() in test_ids:
168 filtered.addTest(test)
169 self.test = filtered
143 if not self.listtests:170 if not self.listtests:
144 self.runTests()171 self.runTests()
145 else:172 else:
@@ -167,7 +194,7 @@
167194
168 import getopt195 import getopt
169 long_opts = ['help', 'verbose', 'quiet', 'failfast', 'catch', 'buffer',196 long_opts = ['help', 'verbose', 'quiet', 'failfast', 'catch', 'buffer',
170 'list']197 'list', 'load-list=']
171 try:198 try:
172 options, args = getopt.getopt(argv[1:], 'hHvqfcbl', long_opts)199 options, args = getopt.getopt(argv[1:], 'hHvqfcbl', long_opts)
173 for opt, value in options:200 for opt, value in options:
@@ -191,6 +218,8 @@
191 # Should this raise an exception if -b is not valid?218 # Should this raise an exception if -b is not valid?
192 if opt in ('-l', '--list'):219 if opt in ('-l', '--list'):
193 self.listtests = True220 self.listtests = True
221 if opt == '--load-list':
222 self.load_list = value
194 if len(args) == 0 and self.defaultTest is None:223 if len(args) == 0 and self.defaultTest is None:
195 # createTests will load tests from self.module224 # createTests will load tests from self.module
196 self.testNames = None225 self.testNames = None
@@ -240,6 +269,8 @@
240 help='Top level directory of project (defaults to start directory)')269 help='Top level directory of project (defaults to start directory)')
241 parser.add_option('-l', '--list', dest='listtests', default=False,270 parser.add_option('-l', '--list', dest='listtests', default=False,
242 help='List tests rather than running them.')271 help='List tests rather than running them.')
272 parser.add_option('--load-list', dest='load_list', default=None,
273 help='Specify a filename containing the test ids to use.')
243274
244 options, args = parser.parse_args(argv)275 options, args = parser.parse_args(argv)
245 if len(args) > 3:276 if len(args) > 3:
@@ -257,6 +288,7 @@
257 if self.buffer is None:288 if self.buffer is None:
258 self.buffer = options.buffer289 self.buffer = options.buffer
259 self.listtests = options.listtests290 self.listtests = options.listtests
291 self.load_list = options.load_list
260292
261 if options.verbose:293 if options.verbose:
262 self.verbosity = 2294 self.verbosity = 2
263295
=== 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 @@
49testtools.runexample.TestFoo.test_quux49testtools.runexample.TestFoo.test_quux
50""", out.getvalue())50""", out.getvalue())
5151
52 def test_run_load_list(self):
53 if fixtures is None:
54 self.skipTest("Need fixtures")
55 package = self.useFixture(SampleTestFixture())
56 out = StringIO.StringIO()
57 # We load two tests - one that exists and one that doesn't, and we
58 # should get the one that exists and neither the one that doesn't nor
59 # the unmentioned one that does.
60 tempdir = self.useFixture(fixtures.TempDir())
61 tempname = tempdir.path + '/tests.list'
62 f = open(tempname, 'wb')
63 try:
64 f.write("""
65testtools.runexample.TestFoo.test_bar
66testtools.runexample.missingtest
67""")
68 finally:
69 f.close()
70 run.main(['prog', '-l', '--load-list', tempname,
71 'testtools.runexample.test_suite'], out)
72 self.assertEqual("""testtools.runexample.TestFoo.test_bar
73""", out.getvalue())
74
52def test_suite():75def test_suite():
53 from unittest import TestLoader76 from unittest import TestLoader
54 return TestLoader().loadTestsFromName(__name__)77 return TestLoader().loadTestsFromName(__name__)

Subscribers

People subscribed via source and target branches