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
1=== modified file 'NEWS'
2--- NEWS 2010-11-29 20:32:00 +0000
3+++ NEWS 2010-11-29 23:47:53 +0000
4@@ -62,6 +62,12 @@
5 them. This is useful for integration with external test analysis/processing
6 tools like subunit and testrepository. (Robert Collins)
7
8+* ``testtools.run`` now supports ``--load-list``, which takes a file containing
9+ test ids, one per line, and intersects those ids with the tests found. This
10+ allows fine grained control of what tests are run even when the tests cannot
11+ be named as objects to import (e.g. due to test parameterisation via
12+ testscenarios). (Robert Collins)
13+
14 * Update documentation to say how to use testtools.run() on Python 2.4.
15 (Jonathan Lange, #501174)
16
17
18=== modified file 'testtools/run.py'
19--- testtools/run.py 2010-11-29 20:32:00 +0000
20+++ testtools/run.py 2010-11-29 23:47:53 +0000
21@@ -62,6 +62,12 @@
22 # removed.
23 # - A tweak has been added to detect 'python -m *.run' and use a
24 # better progName in that case.
25+# - self.module is more comprehensively set to None when being invoked from
26+# the commandline - __name__ is used as a sentinel value.
27+# - --list has been added which can list tests (should be upstreamed).
28+# - --load-list has been added which can reduce the tests used (should be
29+# upstreamed).
30+# - The limitation of using getopt is declared to the user.
31
32 FAILFAST = " -f, --failfast Stop on first failure\n"
33 CATCHBREAK = " -c, --catch Catch control-C and display results\n"
34@@ -75,14 +81,16 @@
35 -v, --verbose Verbose output
36 -q, --quiet Minimal output
37 -l, --list List tests rather than executing them.
38+ --load-list Specifies a file containing test ids, only tests matching
39+ those ids are executed.
40 %(failfast)s%(catchbreak)s%(buffer)s
41 Examples:
42 %(progName)s test_module - run tests from test_module
43 %(progName)s module.TestClass - run tests from module.TestClass
44 %(progName)s module.Class.test_method - run specified test method
45
46-[tests] can be a list of any number of test modules, classes and test
47-methods.
48+All options must come before [tests]. [tests] can be a list of any number of
49+test modules, classes and test methods.
50
51 Alternative Usage: %(progName)s discover [options]
52
53@@ -93,6 +101,8 @@
54 -t directory Top level directory of project (default to
55 start directory)
56 -l, --list List tests rather than executing them.
57+ --load-list Specifies a file containing test ids, only tests matching
58+ those ids are executed.
59
60 For test discovery all test modules must be importable from the top
61 level directory of the project.
62@@ -130,6 +140,7 @@
63 self.buffer = buffer
64 self.defaultTest = defaultTest
65 self.listtests = False
66+ self.load_list = None
67 self.testRunner = testRunner
68 self.testLoader = testLoader
69 progName = argv[0]
70@@ -140,6 +151,22 @@
71 progName = os.path.basename(argv[0])
72 self.progName = progName
73 self.parseArgs(argv)
74+ if self.load_list:
75+ # TODO: preserve existing suites (like testresources does in
76+ # OptimisingTestSuite.add, but with a standard protocol).
77+ # This is needed because the load_tests hook allows arbitrary
78+ # suites, even if that is rarely used.
79+ source = file(self.load_list, 'rb')
80+ try:
81+ lines = source.readlines()
82+ finally:
83+ source.close()
84+ test_ids = set(line.strip() for line in lines)
85+ filtered = unittest.TestSuite()
86+ for test in iterate_tests(self.test):
87+ if test.id() in test_ids:
88+ filtered.addTest(test)
89+ self.test = filtered
90 if not self.listtests:
91 self.runTests()
92 else:
93@@ -167,7 +194,7 @@
94
95 import getopt
96 long_opts = ['help', 'verbose', 'quiet', 'failfast', 'catch', 'buffer',
97- 'list']
98+ 'list', 'load-list=']
99 try:
100 options, args = getopt.getopt(argv[1:], 'hHvqfcbl', long_opts)
101 for opt, value in options:
102@@ -191,6 +218,8 @@
103 # Should this raise an exception if -b is not valid?
104 if opt in ('-l', '--list'):
105 self.listtests = True
106+ if opt == '--load-list':
107+ self.load_list = value
108 if len(args) == 0 and self.defaultTest is None:
109 # createTests will load tests from self.module
110 self.testNames = None
111@@ -240,6 +269,8 @@
112 help='Top level directory of project (defaults to start directory)')
113 parser.add_option('-l', '--list', dest='listtests', default=False,
114 help='List tests rather than running them.')
115+ parser.add_option('--load-list', dest='load_list', default=None,
116+ help='Specify a filename containing the test ids to use.')
117
118 options, args = parser.parse_args(argv)
119 if len(args) > 3:
120@@ -257,6 +288,7 @@
121 if self.buffer is None:
122 self.buffer = options.buffer
123 self.listtests = options.listtests
124+ self.load_list = options.load_list
125
126 if options.verbose:
127 self.verbosity = 2
128
129=== modified file 'testtools/tests/test_run.py'
130--- testtools/tests/test_run.py 2010-11-29 23:09:22 +0000
131+++ testtools/tests/test_run.py 2010-11-29 23:47:53 +0000
132@@ -49,6 +49,29 @@
133 testtools.runexample.TestFoo.test_quux
134 """, out.getvalue())
135
136+ def test_run_load_list(self):
137+ if fixtures is None:
138+ self.skipTest("Need fixtures")
139+ package = self.useFixture(SampleTestFixture())
140+ out = StringIO.StringIO()
141+ # We load two tests - one that exists and one that doesn't, and we
142+ # should get the one that exists and neither the one that doesn't nor
143+ # the unmentioned one that does.
144+ tempdir = self.useFixture(fixtures.TempDir())
145+ tempname = tempdir.path + '/tests.list'
146+ f = open(tempname, 'wb')
147+ try:
148+ f.write("""
149+testtools.runexample.TestFoo.test_bar
150+testtools.runexample.missingtest
151+""")
152+ finally:
153+ f.close()
154+ run.main(['prog', '-l', '--load-list', tempname,
155+ 'testtools.runexample.test_suite'], out)
156+ self.assertEqual("""testtools.runexample.TestFoo.test_bar
157+""", out.getvalue())
158+
159 def test_suite():
160 from unittest import TestLoader
161 return TestLoader().loadTestsFromName(__name__)

Subscribers

People subscribed via source and target branches