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
=== modified file 'bin/u1lint'
--- bin/u1lint 2011-11-10 20:32:35 +0000
+++ bin/u1lint 2011-11-21 20:08:24 +0000
@@ -4,7 +4,7 @@
4#4#
5# Author: Rodney Dawes <rodney.dawes@canonical.com>5# Author: Rodney Dawes <rodney.dawes@canonical.com>
6#6#
7# Copyright 2009-2010 Canonical Ltd.7# Copyright 2009-2011 Canonical Ltd.
8#8#
9# This program is free software: you can redistribute it and/or modify it9# This program is free software: you can redistribute it and/or modify it
10# under the terms of the GNU General Public License version 3, as published10# under the terms of the GNU General Public License version 3, as published
@@ -209,7 +209,7 @@
209 else:209 else:
210 pylint_args = get_subprocess_start_info('pylint')210 pylint_args = get_subprocess_start_info('pylint')
211 # append the extra args to the start info211 # append the extra args to the start info
212 pylint_args.extend(['--output-format=parseable', 212 pylint_args.extend(['--output-format=parseable',
213 '--include-ids=yes'])213 '--include-ids=yes'])
214 if PYLINTRC:214 if PYLINTRC:
215 pylint_args.append("--rcfile=" + PYLINTRC)215 pylint_args.append("--rcfile=" + PYLINTRC)
216216
=== modified file 'bin/u1trial'
--- bin/u1trial 2011-10-24 15:55:17 +0000
+++ bin/u1trial 2011-11-21 20:08:24 +0000
@@ -4,7 +4,7 @@
4#4#
5# Author: Rodney Dawes <rodney.dawes@canonical.com>5# Author: Rodney Dawes <rodney.dawes@canonical.com>
6#6#
7# Copyright 2009-2010 Canonical Ltd.7# Copyright 2009-2011 Canonical Ltd.
8#8#
9# This program is free software: you can redistribute it and/or modify it9# This program is free software: you can redistribute it and/or modify it
10# under the terms of the GNU General Public License version 3, as published10# under the terms of the GNU General Public License version 3, as published
@@ -28,12 +28,15 @@
28import sys28import sys
29import unittest29import unittest
3030
31from twisted.python.usage import UsageError
32from twisted.scripts import trial
31from twisted.trial.runner import TrialRunner33from twisted.trial.runner import TrialRunner
3234
33sys.path.insert(0, os.path.abspath("."))35sys.path.insert(0, os.path.abspath("."))
3436
35from ubuntuone.devtools.testing.txcheck import TXCheckSuite37from ubuntuone.devtools.testing.txcheck import TXCheckSuite
3638
39
37def _is_in_ignored_path(testcase, paths):40def _is_in_ignored_path(testcase, paths):
38 """Return if the testcase is in one of the ignored paths."""41 """Return if the testcase is in one of the ignored paths."""
39 for ignored_path in paths:42 for ignored_path in paths:
@@ -45,12 +48,10 @@
45class TestRunner(TrialRunner):48class TestRunner(TrialRunner):
46 """The test runner implementation."""49 """The test runner implementation."""
4750
48 def __init__(self, force_gc=False):51 def __init__(self, config=None):
49 from twisted.trial.reporter import TreeReporter
50
51 # set $HOME to the _trial_temp dir, to avoid breaking user files52 # set $HOME to the _trial_temp dir, to avoid breaking user files
52 trial_temp_dir = os.environ.get('TRIAL_TEMP_DIR', os.getcwd())53 trial_temp_dir = os.environ.get('TRIAL_TEMP_DIR', os.getcwd())
53 homedir = os.path.join(trial_temp_dir, '_trial_temp')54 homedir = os.path.join(trial_temp_dir, config['temp-directory'])
54 os.environ['HOME'] = homedir55 os.environ['HOME'] = homedir
5556
56 # setup $XDG_*_HOME variables and create the directories57 # setup $XDG_*_HOME variables and create the directories
@@ -71,12 +72,29 @@
71 # setup the ROOTDIR env var72 # setup the ROOTDIR env var
72 os.environ['ROOTDIR'] = os.getcwd()73 os.environ['ROOTDIR'] = os.getcwd()
7374
75 # Need an attribute for tempdir so we can use it later
74 self.tempdir = homedir76 self.tempdir = homedir
75 working_dir = os.path.join(self.tempdir, 'tmp')77 working_dir = os.path.join(self.tempdir, 'trial')
76 super(TestRunner, self).__init__(reporterFactory=TreeReporter,78
77 realTimeErrors=True,79 # Handle running trial in debug or dry-run mode
78 workingDirectory=working_dir,80 mode = None
79 forceGarbageCollection=force_gc)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
80 self.required_services = []98 self.required_services = []
81 self.source_files = []99 self.source_files = []
82100
@@ -117,18 +135,6 @@
117 pattern = re.compile('.*%s.*' % test_pattern)135 pattern = re.compile('.*%s.*' % test_pattern)
118 else:136 else:
119 pattern = None137 pattern = None
120
121 # get the ignored modules/tests
122 if ignored_modules:
123 ignored_modules = map(str.strip, ignored_modules.split(','))
124 else:
125 ignored_modules = []
126
127 # get the ignored paths
128 if ignored_paths:
129 ignored_paths = map(str.strip, ignored_paths.split(','))
130 else:
131 ignored_paths = []
132138
133 # Disable this lint warning as we need to access _tests in the139 # Disable this lint warning as we need to access _tests in the
134 # test suites, to collect the tests140 # test suites, to collect the tests
@@ -169,100 +175,150 @@
169 suite.addTests(module_suite)175 suite.addTests(module_suite)
170 return suite176 return suite
171177
172 # pylint: disable=E0202178 def get_suite(self, config):
173 def run(self, args, options=None):179 """Get the test suite to use."""
180 suite = unittest.TestSuite()
181 for path in config['tests']:
182 suite.addTest(self._collect_tests(path, config['test'],
183 config['ignore-modules'],
184 config['ignore-paths']))
185 if config['loop']:
186 old_suite = suite
187 suite = unittest.TestSuite()
188 for _ in xrange(config['loop']):
189 suite.addTest(old_suite)
190
191 return suite
192
193 # pylint: disable=C0103
194 def _runWithoutDecoration(self, test):
174 """run the tests."""195 """run the tests."""
175 success = 0196 result = None
176 running_services = []197 running_services = []
177 if options.coverage:
178 coverage.erase()
179 coverage.start()
180198
181 try:199 try:
182 suite = unittest.TestSuite()
183 for path in args:
184 print "Adding path"
185 suite.addTest(self._collect_tests(path, options.test,
186 options.ignored_modules,
187 options.ignored_paths))
188 if options.loops:
189 old_suite = suite
190 suite = unittest.TestSuite()
191 for _ in xrange(options.loops):
192 suite.addTest(old_suite)
193
194 # Start any required services200 # Start any required services
195 for service in self.required_services:201 for service in self.required_services:
196 runner = service()202 runner = service()
197 runner.start_service(tempdir=self.tempdir)203 runner.start_service(tempdir=self.tempdir)
198 running_services.append(runner)204 running_services.append(runner)
199205
200 result = super(TestRunner, self).run(suite)206 result = super(TestRunner, self)._runWithoutDecoration(test)
201 success = result.wasSuccessful()
202 finally:207 finally:
203 # Stop all the running services208 # Stop all the running services
204 for runner in running_services:209 for runner in running_services:
205 runner.stop_service()210 runner.stop_service()
206211
207 if options.coverage:212 return result
208 coverage.stop()213
209 coverage.report(self.source_files, ignore_errors=True,214
210 show_missing=False)215class Options(trial.Options):
211216 """Class for options handling."""
212 if not success:217
213 sys.exit(1)218 optFlags = [["coverage", "c"],
214 else:219 ["gui", None],
215 sys.exit(0)220 ["help-reactors", None],
221 ]
222
223 optParameters = [["test", "t", None],
224 ["loop", None, 1],
225 ["ignore-modules", "i", ""],
226 ["ignore-paths", "p", ""],
227 ["reactor", "r", "glib"],
228 ]
229
230 def __init__(self):
231 self['tests'] = set()
232 super(Options, self).__init__()
233 self['rterrors'] = True
234
235 def opt_coverage(self):
236 """Generate a coverage report for the run tests"""
237 self['coverage'] = True
238
239 def opt_gui(self):
240 """Use the GUI mode of some reactors"""
241 self['gui'] = True
242
243 def opt_help_reactors(self):
244 """Help on available reactors for use with tests"""
245 synopsis = ('')
246 print synopsis
247 print 'Need to get list of reactors and print them here.'
248 print
249 sys.exit(0)
250
251 def opt_test(self, option):
252 """Run specific tests, e.g: className.methodName"""
253 self['test'] = option
254
255 def opt_loop(self, option):
256 """Loop tests the specified number of times."""
257 try:
258 self['loop'] = long(option)
259 except ValueError:
260 raise UsageError('A positive integer value must be specified.')
261
262 def opt_ignore_modules(self, option):
263 """Comma-separate list of test modules to ignore,
264 e.g: test_gtk.py, test_account.py
265 """
266 self['ignore-modules'] = map(str.strip, option.split(','))
267
268 def opt_ignore_paths(self, option):
269 """Comma-separated list of relative paths to ignore,
270 e.g: tests/platform/windows, tests/platform/macosx
271 """
272 self['ignore-paths'] = map(str.strip, option.split(','))
273
274 def opt_reactor(self, option):
275 """Which reactor to use (see --help-reactors for a list
276 of possibilities)
277 """
278 self['reactor'] = option
279 opt_r = opt_reactor
216280
217281
218def main():282def main():
219 """Do the deed."""283 """Do the deed."""
220 from optparse import OptionParser284 if len(sys.argv) == 1:
221 usage = '%prog [options] path'285 sys.argv.append('--help')
222 parser = OptionParser(usage=usage)286
223 parser.add_option("-t", "--test", dest="test",287 config = Options()
224 help = "run specific tests, e.g: className.methodName")288 config.parseOptions()
225 parser.add_option("-l", "--loop", dest="loops", type="int", default=1,
226 help = "loop selected tests LOOPS number of times",
227 metavar="LOOPS")
228 parser.add_option("-c", "--coverage", action="store_true", dest="coverage",
229 help="print a coverage report when finished")
230 parser.add_option("-i", "--ignored-modules", dest="ignored_modules",
231 default=None, help="comma-separated test moodules "
232 + "to ignore, e.g: test_gtk.py, test_account.py")
233 parser.add_option("-p", "--ignore-paths", dest="ignored_paths",
234 default=None, help="comma-separated relative "
235 + "paths to ignore. "
236 + "e.g: tests/platform/windows, tests/platform/macosx")
237 parser.add_option("--force-gc", action="store_true", dest="force_gc",
238 default=False, help="Run gc.collect() before and after "
239 "each test case.")
240 parser.add_option("--reactor", type="string", dest="reactor",
241 default='glib',
242 help="Run the tests using the specified reactor.",
243 metavar="REACTOR")
244 parser.add_option("--gui", action="store_true", dest="use_gui",
245 help="Use the GUI mode of some reactors.")
246 (options, args) = parser.parse_args()
247 if not args:
248 parser.print_help()
249 sys.exit(2)
250289
251 try:290 try:
252 reactor_name = 'ubuntuone.devtools.reactors.%s' % options.reactor291 reactor_name = 'ubuntuone.devtools.reactors.%s' % config['reactor']
253 reactor = __import__(reactor_name, None, None, [''])292 reactor = __import__(reactor_name, None, None, [''])
254 except ImportError:293 except ImportError:
255 print 'The specified reactor is not supported.'294 print 'The specified reactor is not supported.'
256 sys.exit(1)295 sys.exit(1)
257 else:296 else:
258 try:297 try:
259 reactor.install(options=options)298 reactor.install(options=config)
260 except ImportError:299 except ImportError:
261 print('The Python package providing the requested reactor is not '300 print('The Python package providing the requested reactor is not '
262 'installed. You can find it here: %s' % reactor.REACTOR_URL)301 'installed. You can find it here: %s' % reactor.REACTOR_URL)
263 raise302 raise
264303
265 TestRunner(force_gc=options.force_gc).run(args, options)304 trial_runner = TestRunner(config=config)
305 suite = trial_runner.get_suite(config)
306
307 if config['coverage']:
308 coverage.erase()
309 coverage.start()
310
311 if config['until-failure']:
312 result = trial_runner.runUntilFailure(suite)
313 else:
314 result = trial_runner.run(suite)
315
316 if config['coverage']:
317 coverage.stop()
318 coverage.report(trial_runner.source_files, ignore_errors=True,
319 show_missing=False)
320
321 sys.exit(not result.wasSuccessful())
266322
267323
268if __name__ == '__main__':324if __name__ == '__main__':
269325
=== modified file 'run-tests'
--- run-tests 2011-05-26 15:49:41 +0000
+++ run-tests 2011-11-21 20:08:24 +0000
@@ -1,7 +1,7 @@
1#!/bin/bash1#!/bin/bash
2# Author: Natalia Bidart <natalia.bidart@canonical.com>2# Author: Natalia Bidart <natalia.bidart@canonical.com>
3#3#
4# Copyright 2010 Canonical Ltd.4# Copyright 2010-2011 Canonical Ltd.
5#5#
6# This program is free software: you can redistribute it and/or modify it6# This program is free software: you can redistribute it and/or modify it
7# under the terms of the GNU General Public License version 3, as published7# under the terms of the GNU General Public License version 3, as published
@@ -18,7 +18,8 @@
1818
19bin/u1trial -c ubuntuone19bin/u1trial -c ubuntuone
20bin/u1trial --reactor=twisted ubuntuone20bin/u1trial --reactor=twisted ubuntuone
21echo "Running style checks..."
21bin/u1lint22bin/u1lint
22pep8 --repeat .23pep8 --repeat . bin/*
23rm -rf _trial_temp24rm -rf _trial_temp
24rm -rf .coverage25rm -rf .coverage
2526
=== modified file 'ubuntuone/devtools/reactors/glib.py'
--- ubuntuone/devtools/reactors/glib.py 2011-05-26 15:49:41 +0000
+++ ubuntuone/devtools/reactors/glib.py 2011-11-21 20:08:24 +0000
@@ -17,7 +17,7 @@
17def install(options=None):17def install(options=None):
18 """Install the reactor and parse any options we might need."""18 """Install the reactor and parse any options we might need."""
19 reactor_name = None19 reactor_name = None
20 if options is not None and options.use_gui:20 if options is not None and options['gui']:
21 reactor_name = 'twisted.internet.gtk2reactor'21 reactor_name = 'twisted.internet.gtk2reactor'
22 else:22 else:
23 reactor_name = 'twisted.internet.glib2reactor'23 reactor_name = 'twisted.internet.glib2reactor'
2424
=== modified file 'ubuntuone/devtools/reactors/qt4.py'
--- ubuntuone/devtools/reactors/qt4.py 2011-11-11 13:31:18 +0000
+++ ubuntuone/devtools/reactors/qt4.py 2011-11-21 20:08:24 +0000
@@ -22,7 +22,7 @@
2222
23def install(options=None):23def install(options=None):
24 """Install the reactor and parse any options we might need."""24 """Install the reactor and parse any options we might need."""
25 if options is not None and options.use_gui:25 if options is not None and options['gui']:
26 from PyQt4.QtGui import QApplication26 from PyQt4.QtGui import QApplication
27 # We must assign this to a variable, or we will get crashes in Qt27 # We must assign this to a variable, or we will get crashes in Qt
28 # pylint: disable=W061228 # pylint: disable=W0612
2929
=== modified file 'ubuntuone/devtools/services/tests/test_dbus.py'
--- ubuntuone/devtools/services/tests/test_dbus.py 2011-02-03 14:32:01 +0000
+++ ubuntuone/devtools/services/tests/test_dbus.py 2011-11-21 20:08:24 +0000
@@ -1,6 +1,7 @@
1"""Tests for the test runner."""1"""Tests for the test runner."""
22
3import os3import os
4import shutil
45
5from ubuntuone.devtools.testcase import DBusTestCase6from ubuntuone.devtools.testcase import DBusTestCase
6from ubuntuone.devtools.services.dbus import DBusRunner7from ubuntuone.devtools.services.dbus import DBusRunner
@@ -25,4 +26,5 @@
25 # pylint: disable=W021226 # pylint: disable=W0212
26 os.makedirs(self.tmpdir)27 os.makedirs(self.tmpdir)
27 runner._find_config_file(tempdir=self.tmpdir)28 runner._find_config_file(tempdir=self.tmpdir)
29 shutil.rmtree(self.tmpdir)
28 self.assertEqual(expected, runner.config_file)30 self.assertEqual(expected, runner.config_file)

Subscribers

People subscribed via source and target branches

to all changes: