Merge lp:~dobey/ubuntuone-dev-tools/trial-args into lp:ubuntuone-dev-tools

Proposed by dobey
Status: Merged
Approved by: Roberto Alsina
Approved revision: 51
Merged at revision: 48
Proposed branch: lp:~dobey/ubuntuone-dev-tools/trial-args
Merge into: lp:ubuntuone-dev-tools
Diff against target: 399 lines (+149/-90)
6 files modified
bin/u1lint (+2/-2)
bin/u1trial (+140/-84)
run-tests (+3/-2)
ubuntuone/devtools/reactors/glib.py (+1/-1)
ubuntuone/devtools/reactors/qt4.py (+1/-1)
ubuntuone/devtools/services/tests/test_dbus.py (+2/-0)
To merge this branch: bzr merge lp:~dobey/ubuntuone-dev-tools/trial-args
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Sidnei da Silva (community) Approve
Review via email: mp+82758@code.launchpad.net

Commit message

Use the Options handling API of trial so unhandled options get passed through
Fix some style issues
Make test_dbus work with --loop argument

To post a comment you must log in.
49. By dobey

Also need to override opt_r in Options

Revision history for this message
Sidnei da Silva (sidnei) wrote :

1. Typo at 'Need to et list of reactors and print them here.'

2. Does help-reactors need to be overriden? Seems like trial already implements it.

Other than that that, +1!

review: Approve
50. By dobey

Update (C) years also

51. By dobey

Fix the typo from review

Revision history for this message
dobey (dobey) wrote :

On Mon, 2011-11-21 at 19:37 +0000, Sidnei da Silva wrote:
> 2. Does help-reactors need to be overriden? Seems like trial already implements it.

Typo fixed. And yes, we need to override it, as we support some reactors
which are not installed in the twisted directory, as well as needing to
do some additional work on top of just importing them, for running some
tests that poke at the UI. I would be very happy to not have to
implement the reactor bits here, but for now we have to. :)

Revision history for this message
Roberto Alsina (ralsina) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/u1lint'
2--- bin/u1lint 2011-11-10 20:32:35 +0000
3+++ bin/u1lint 2011-11-21 20:08:24 +0000
4@@ -4,7 +4,7 @@
5 #
6 # Author: Rodney Dawes <rodney.dawes@canonical.com>
7 #
8-# Copyright 2009-2010 Canonical Ltd.
9+# Copyright 2009-2011 Canonical Ltd.
10 #
11 # This program is free software: you can redistribute it and/or modify it
12 # under the terms of the GNU General Public License version 3, as published
13@@ -209,7 +209,7 @@
14 else:
15 pylint_args = get_subprocess_start_info('pylint')
16 # append the extra args to the start info
17- pylint_args.extend(['--output-format=parseable',
18+ pylint_args.extend(['--output-format=parseable',
19 '--include-ids=yes'])
20 if PYLINTRC:
21 pylint_args.append("--rcfile=" + PYLINTRC)
22
23=== modified file 'bin/u1trial'
24--- bin/u1trial 2011-10-24 15:55:17 +0000
25+++ bin/u1trial 2011-11-21 20:08:24 +0000
26@@ -4,7 +4,7 @@
27 #
28 # Author: Rodney Dawes <rodney.dawes@canonical.com>
29 #
30-# Copyright 2009-2010 Canonical Ltd.
31+# Copyright 2009-2011 Canonical Ltd.
32 #
33 # This program is free software: you can redistribute it and/or modify it
34 # under the terms of the GNU General Public License version 3, as published
35@@ -28,12 +28,15 @@
36 import sys
37 import unittest
38
39+from twisted.python.usage import UsageError
40+from twisted.scripts import trial
41 from twisted.trial.runner import TrialRunner
42
43 sys.path.insert(0, os.path.abspath("."))
44
45 from ubuntuone.devtools.testing.txcheck import TXCheckSuite
46
47+
48 def _is_in_ignored_path(testcase, paths):
49 """Return if the testcase is in one of the ignored paths."""
50 for ignored_path in paths:
51@@ -45,12 +48,10 @@
52 class TestRunner(TrialRunner):
53 """The test runner implementation."""
54
55- def __init__(self, force_gc=False):
56- from twisted.trial.reporter import TreeReporter
57-
58+ def __init__(self, config=None):
59 # set $HOME to the _trial_temp dir, to avoid breaking user files
60 trial_temp_dir = os.environ.get('TRIAL_TEMP_DIR', os.getcwd())
61- homedir = os.path.join(trial_temp_dir, '_trial_temp')
62+ homedir = os.path.join(trial_temp_dir, config['temp-directory'])
63 os.environ['HOME'] = homedir
64
65 # setup $XDG_*_HOME variables and create the directories
66@@ -71,12 +72,29 @@
67 # setup the ROOTDIR env var
68 os.environ['ROOTDIR'] = os.getcwd()
69
70+ # Need an attribute for tempdir so we can use it later
71 self.tempdir = homedir
72- working_dir = os.path.join(self.tempdir, 'tmp')
73- super(TestRunner, self).__init__(reporterFactory=TreeReporter,
74- realTimeErrors=True,
75- workingDirectory=working_dir,
76- forceGarbageCollection=force_gc)
77+ working_dir = os.path.join(self.tempdir, 'trial')
78+
79+ # Handle running trial in debug or dry-run mode
80+ mode = None
81+ if config['debug']:
82+ mode = TrialRunner.DEBUG
83+ if config['dry-run']:
84+ mode = TrialRunner.DRY_RUN
85+
86+ # Hook up to the parent test runner
87+ super(TestRunner, self).__init__(
88+ reporterFactory=config['reporter'],
89+ mode=mode,
90+ profile=config['profile'],
91+ logfile=config['logfile'],
92+ tracebackFormat=config['tbformat'],
93+ realTimeErrors=config['rterrors'],
94+ uncleanWarnings=config['unclean-warnings'],
95+ workingDirectory=working_dir,
96+ forceGarbageCollection=config['force-gc'])
97+
98 self.required_services = []
99 self.source_files = []
100
101@@ -117,18 +135,6 @@
102 pattern = re.compile('.*%s.*' % test_pattern)
103 else:
104 pattern = None
105-
106- # get the ignored modules/tests
107- if ignored_modules:
108- ignored_modules = map(str.strip, ignored_modules.split(','))
109- else:
110- ignored_modules = []
111-
112- # get the ignored paths
113- if ignored_paths:
114- ignored_paths = map(str.strip, ignored_paths.split(','))
115- else:
116- ignored_paths = []
117
118 # Disable this lint warning as we need to access _tests in the
119 # test suites, to collect the tests
120@@ -169,100 +175,150 @@
121 suite.addTests(module_suite)
122 return suite
123
124- # pylint: disable=E0202
125- def run(self, args, options=None):
126+ def get_suite(self, config):
127+ """Get the test suite to use."""
128+ suite = unittest.TestSuite()
129+ for path in config['tests']:
130+ suite.addTest(self._collect_tests(path, config['test'],
131+ config['ignore-modules'],
132+ config['ignore-paths']))
133+ if config['loop']:
134+ old_suite = suite
135+ suite = unittest.TestSuite()
136+ for _ in xrange(config['loop']):
137+ suite.addTest(old_suite)
138+
139+ return suite
140+
141+ # pylint: disable=C0103
142+ def _runWithoutDecoration(self, test):
143 """run the tests."""
144- success = 0
145+ result = None
146 running_services = []
147- if options.coverage:
148- coverage.erase()
149- coverage.start()
150
151 try:
152- suite = unittest.TestSuite()
153- for path in args:
154- print "Adding path"
155- suite.addTest(self._collect_tests(path, options.test,
156- options.ignored_modules,
157- options.ignored_paths))
158- if options.loops:
159- old_suite = suite
160- suite = unittest.TestSuite()
161- for _ in xrange(options.loops):
162- suite.addTest(old_suite)
163-
164 # Start any required services
165 for service in self.required_services:
166 runner = service()
167 runner.start_service(tempdir=self.tempdir)
168 running_services.append(runner)
169
170- result = super(TestRunner, self).run(suite)
171- success = result.wasSuccessful()
172+ result = super(TestRunner, self)._runWithoutDecoration(test)
173 finally:
174 # Stop all the running services
175 for runner in running_services:
176 runner.stop_service()
177
178- if options.coverage:
179- coverage.stop()
180- coverage.report(self.source_files, ignore_errors=True,
181- show_missing=False)
182-
183- if not success:
184- sys.exit(1)
185- else:
186- sys.exit(0)
187+ return result
188+
189+
190+class Options(trial.Options):
191+ """Class for options handling."""
192+
193+ optFlags = [["coverage", "c"],
194+ ["gui", None],
195+ ["help-reactors", None],
196+ ]
197+
198+ optParameters = [["test", "t", None],
199+ ["loop", None, 1],
200+ ["ignore-modules", "i", ""],
201+ ["ignore-paths", "p", ""],
202+ ["reactor", "r", "glib"],
203+ ]
204+
205+ def __init__(self):
206+ self['tests'] = set()
207+ super(Options, self).__init__()
208+ self['rterrors'] = True
209+
210+ def opt_coverage(self):
211+ """Generate a coverage report for the run tests"""
212+ self['coverage'] = True
213+
214+ def opt_gui(self):
215+ """Use the GUI mode of some reactors"""
216+ self['gui'] = True
217+
218+ def opt_help_reactors(self):
219+ """Help on available reactors for use with tests"""
220+ synopsis = ('')
221+ print synopsis
222+ print 'Need to get list of reactors and print them here.'
223+ print
224+ sys.exit(0)
225+
226+ def opt_test(self, option):
227+ """Run specific tests, e.g: className.methodName"""
228+ self['test'] = option
229+
230+ def opt_loop(self, option):
231+ """Loop tests the specified number of times."""
232+ try:
233+ self['loop'] = long(option)
234+ except ValueError:
235+ raise UsageError('A positive integer value must be specified.')
236+
237+ def opt_ignore_modules(self, option):
238+ """Comma-separate list of test modules to ignore,
239+ e.g: test_gtk.py, test_account.py
240+ """
241+ self['ignore-modules'] = map(str.strip, option.split(','))
242+
243+ def opt_ignore_paths(self, option):
244+ """Comma-separated list of relative paths to ignore,
245+ e.g: tests/platform/windows, tests/platform/macosx
246+ """
247+ self['ignore-paths'] = map(str.strip, option.split(','))
248+
249+ def opt_reactor(self, option):
250+ """Which reactor to use (see --help-reactors for a list
251+ of possibilities)
252+ """
253+ self['reactor'] = option
254+ opt_r = opt_reactor
255
256
257 def main():
258 """Do the deed."""
259- from optparse import OptionParser
260- usage = '%prog [options] path'
261- parser = OptionParser(usage=usage)
262- parser.add_option("-t", "--test", dest="test",
263- help = "run specific tests, e.g: className.methodName")
264- parser.add_option("-l", "--loop", dest="loops", type="int", default=1,
265- help = "loop selected tests LOOPS number of times",
266- metavar="LOOPS")
267- parser.add_option("-c", "--coverage", action="store_true", dest="coverage",
268- help="print a coverage report when finished")
269- parser.add_option("-i", "--ignored-modules", dest="ignored_modules",
270- default=None, help="comma-separated test moodules "
271- + "to ignore, e.g: test_gtk.py, test_account.py")
272- parser.add_option("-p", "--ignore-paths", dest="ignored_paths",
273- default=None, help="comma-separated relative "
274- + "paths to ignore. "
275- + "e.g: tests/platform/windows, tests/platform/macosx")
276- parser.add_option("--force-gc", action="store_true", dest="force_gc",
277- default=False, help="Run gc.collect() before and after "
278- "each test case.")
279- parser.add_option("--reactor", type="string", dest="reactor",
280- default='glib',
281- help="Run the tests using the specified reactor.",
282- metavar="REACTOR")
283- parser.add_option("--gui", action="store_true", dest="use_gui",
284- help="Use the GUI mode of some reactors.")
285- (options, args) = parser.parse_args()
286- if not args:
287- parser.print_help()
288- sys.exit(2)
289+ if len(sys.argv) == 1:
290+ sys.argv.append('--help')
291+
292+ config = Options()
293+ config.parseOptions()
294
295 try:
296- reactor_name = 'ubuntuone.devtools.reactors.%s' % options.reactor
297+ reactor_name = 'ubuntuone.devtools.reactors.%s' % config['reactor']
298 reactor = __import__(reactor_name, None, None, [''])
299 except ImportError:
300 print 'The specified reactor is not supported.'
301 sys.exit(1)
302 else:
303 try:
304- reactor.install(options=options)
305+ reactor.install(options=config)
306 except ImportError:
307 print('The Python package providing the requested reactor is not '
308 'installed. You can find it here: %s' % reactor.REACTOR_URL)
309 raise
310
311- TestRunner(force_gc=options.force_gc).run(args, options)
312+ trial_runner = TestRunner(config=config)
313+ suite = trial_runner.get_suite(config)
314+
315+ if config['coverage']:
316+ coverage.erase()
317+ coverage.start()
318+
319+ if config['until-failure']:
320+ result = trial_runner.runUntilFailure(suite)
321+ else:
322+ result = trial_runner.run(suite)
323+
324+ if config['coverage']:
325+ coverage.stop()
326+ coverage.report(trial_runner.source_files, ignore_errors=True,
327+ show_missing=False)
328+
329+ sys.exit(not result.wasSuccessful())
330
331
332 if __name__ == '__main__':
333
334=== modified file 'run-tests'
335--- run-tests 2011-05-26 15:49:41 +0000
336+++ run-tests 2011-11-21 20:08:24 +0000
337@@ -1,7 +1,7 @@
338 #!/bin/bash
339 # Author: Natalia Bidart <natalia.bidart@canonical.com>
340 #
341-# Copyright 2010 Canonical Ltd.
342+# Copyright 2010-2011 Canonical Ltd.
343 #
344 # This program is free software: you can redistribute it and/or modify it
345 # under the terms of the GNU General Public License version 3, as published
346@@ -18,7 +18,8 @@
347
348 bin/u1trial -c ubuntuone
349 bin/u1trial --reactor=twisted ubuntuone
350+echo "Running style checks..."
351 bin/u1lint
352-pep8 --repeat .
353+pep8 --repeat . bin/*
354 rm -rf _trial_temp
355 rm -rf .coverage
356
357=== modified file 'ubuntuone/devtools/reactors/glib.py'
358--- ubuntuone/devtools/reactors/glib.py 2011-05-26 15:49:41 +0000
359+++ ubuntuone/devtools/reactors/glib.py 2011-11-21 20:08:24 +0000
360@@ -17,7 +17,7 @@
361 def install(options=None):
362 """Install the reactor and parse any options we might need."""
363 reactor_name = None
364- if options is not None and options.use_gui:
365+ if options is not None and options['gui']:
366 reactor_name = 'twisted.internet.gtk2reactor'
367 else:
368 reactor_name = 'twisted.internet.glib2reactor'
369
370=== modified file 'ubuntuone/devtools/reactors/qt4.py'
371--- ubuntuone/devtools/reactors/qt4.py 2011-11-11 13:31:18 +0000
372+++ ubuntuone/devtools/reactors/qt4.py 2011-11-21 20:08:24 +0000
373@@ -22,7 +22,7 @@
374
375 def install(options=None):
376 """Install the reactor and parse any options we might need."""
377- if options is not None and options.use_gui:
378+ if options is not None and options['gui']:
379 from PyQt4.QtGui import QApplication
380 # We must assign this to a variable, or we will get crashes in Qt
381 # pylint: disable=W0612
382
383=== modified file 'ubuntuone/devtools/services/tests/test_dbus.py'
384--- ubuntuone/devtools/services/tests/test_dbus.py 2011-02-03 14:32:01 +0000
385+++ ubuntuone/devtools/services/tests/test_dbus.py 2011-11-21 20:08:24 +0000
386@@ -1,6 +1,7 @@
387 """Tests for the test runner."""
388
389 import os
390+import shutil
391
392 from ubuntuone.devtools.testcase import DBusTestCase
393 from ubuntuone.devtools.services.dbus import DBusRunner
394@@ -25,4 +26,5 @@
395 # pylint: disable=W0212
396 os.makedirs(self.tmpdir)
397 runner._find_config_file(tempdir=self.tmpdir)
398+ shutil.rmtree(self.tmpdir)
399 self.assertEqual(expected, runner.config_file)

Subscribers

People subscribed via source and target branches

to all changes: