Merge lp:~dobey/ubuntuone-dev-tools/runner-tests into lp:ubuntuone-dev-tools

Proposed by dobey on 2012-08-13
Status: Merged
Approved by: Alejandro J. Cura on 2012-08-14
Approved revision: 82
Merged at revision: 79
Proposed branch: lp:~dobey/ubuntuone-dev-tools/runner-tests
Merge into: lp:ubuntuone-dev-tools
Diff against target: 289 lines (+157/-16)
4 files modified
.bzrignore (+1/-0)
ubuntuone/devtools/runners/__init__.py (+20/-3)
ubuntuone/devtools/tests/test_utils.py (+110/-0)
ubuntuone/devtools/utils.py (+26/-13)
To merge this branch: bzr merge lp:~dobey/ubuntuone-dev-tools/runner-tests
Reviewer Review Type Date Requested Status
Alejandro J. Cura (community) Approve on 2012-08-14
Roberto Alsina (community) 2012-08-13 Approve on 2012-08-14
Review via email: mp+119436@code.launchpad.net

Commit Message

Test the new options parser
Fix up handling of temp-directory and the test path args for non-txrunner usage
Use unicode_literals and print_function
Implement synonyms usage in options so some options work more correctly
Use unicode_literals and print_function
Ignore the .coverage file

To post a comment you must log in.
Roberto Alsina (ralsina) :
review: Approve
Alejandro J. Cura (alecu) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2010-07-14 21:39:08 +0000
3+++ .bzrignore 2012-08-13 21:10:25 +0000
4@@ -1,3 +1,4 @@
5+.coverage
6 MANIFEST
7 build
8 dist
9
10=== modified file 'ubuntuone/devtools/runners/__init__.py'
11--- ubuntuone/devtools/runners/__init__.py 2012-07-27 19:02:53 +0000
12+++ ubuntuone/devtools/runners/__init__.py 2012-08-13 21:10:25 +0000
13@@ -26,6 +26,8 @@
14 # files in the program, then also delete it here.
15 """The base test runner object."""
16
17+from __future__ import print_function, unicode_literals
18+
19 import coverage
20 import gc
21 import inspect
22@@ -195,26 +197,28 @@
23 ['ignore-modules', 'i', '', None],
24 ['ignore-paths', 'p', '', None],
25 ['runner', None, 'txrunner', None],
26+ ['temp-directory', None, '_trial_temp', None],
27 ]
28
29 def __init__(self, *args, **kwargs):
30+ super(BaseTestOptions, self).__init__(*args, **kwargs)
31 self['tests'] = set()
32- super(BaseTestOptions, self).__init__(*args, **kwargs)
33
34 def opt_help_runners(self):
35 """List the runners which are supported."""
36+ sys.exit(0)
37
38 def opt_ignore_modules(self, option):
39 """Comma-separate list of test modules to ignore,
40 e.g: test_gtk.py, test_account.py
41 """
42- self['ignore-modules'] = map(str.strip, option.split(','))
43+ self['ignore-modules'] = map(unicode.strip, option.split(','))
44
45 def opt_ignore_paths(self, option):
46 """Comma-separated list of relative paths to ignore,
47 e.g: tests/platform/windows, tests/platform/macosx
48 """
49- self['ignore-paths'] = map(str.strip, option.split(','))
50+ self['ignore-paths'] = map(unicode.strip, option.split(','))
51
52 def opt_loop(self, option):
53 """Loop tests the specified number of times."""
54@@ -223,10 +227,23 @@
55 except ValueError:
56 raise UsageError('A positive integer value must be specified.')
57
58+ def opt_temp_directory(self, option):
59+ """Path to use as a working directory for tests.
60+ [default: _trial_temp]
61+ """
62+ self['temp-directory'] = option
63+
64 def opt_test(self, option):
65 """Run specific tests, e.g: className.methodName"""
66 self['test'] = option
67
68+ # We use some camelcase names for trial compatibility here.
69+ # pylint: disable=C0103
70+ def parseArgs(self, *args):
71+ """Handle the extra arguments."""
72+ self['tests'].update(args)
73+ # pylint: enable=C0103
74+
75
76 def _get_runner_options(runner_name):
77 """Return the test runner module, and its options object."""
78
79=== added file 'ubuntuone/devtools/tests/test_utils.py'
80--- ubuntuone/devtools/tests/test_utils.py 1970-01-01 00:00:00 +0000
81+++ ubuntuone/devtools/tests/test_utils.py 2012-08-13 21:10:25 +0000
82@@ -0,0 +1,110 @@
83+# -*- coding: utf-8 -*-
84+#
85+# Copyright 2012 Canonical Ltd.
86+#
87+# This program is free software: you can redistribute it and/or modify it
88+# under the terms of the GNU General Public License version 3, as published
89+# by the Free Software Foundation.
90+#
91+# This program is distributed in the hope that it will be useful, but
92+# WITHOUT ANY WARRANTY; without even the implied warranties of
93+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
94+# PURPOSE. See the GNU General Public License for more details.
95+#
96+# You should have received a copy of the GNU General Public License along
97+# with this program. If not, see <http://www.gnu.org/licenses/>.
98+#
99+# In addition, as a special exception, the copyright holders give
100+# permission to link the code of portions of this program with the
101+# OpenSSL library under certain conditions as described in each
102+# individual source file, and distribute linked combinations
103+# including the two.
104+# You must obey the GNU General Public License in all respects
105+# for all of the code used other than OpenSSL. If you modify
106+# file(s) with this exception, you may extend this exception to your
107+# version of the file(s), but you are not obligated to do so. If you
108+# do not wish to do so, delete this exception statement from your
109+# version. If you delete this exception statement from all source
110+# files in the program, then also delete it here.
111+"""Test the utils module."""
112+
113+from __future__ import print_function, unicode_literals
114+
115+from twisted.internet.defer import inlineCallbacks
116+from ubuntuone.devtools.errors import UsageError
117+from ubuntuone.devtools.testcases import BaseTestCase
118+from ubuntuone.devtools.utils import OptionParser
119+
120+
121+class FakeOptions(OptionParser):
122+ """Fake options class for testing."""
123+
124+ optFlags = [['foo', 'f', 'Save the manatees.'],
125+ ['bar', None, 'Beyond all recognition.'],
126+ ]
127+
128+ optParameters = [['stuff', 's', 'things'],
129+ ]
130+
131+ def __init__(self, *args, **kwargs):
132+ super(FakeOptions, self).__init__(*args, **kwargs)
133+
134+ def opt_foo(self):
135+ """Handle the foo flag."""
136+ pass
137+
138+ def opt_stuff(self, option):
139+ """Handle the stuff option."""
140+ self['stuff'] = option
141+
142+
143+class OptionParserTestCase(BaseTestCase):
144+ """Test the OptionParser class."""
145+
146+ @inlineCallbacks
147+ def setUp(self, *args, **kwargs):
148+ yield super(OptionParserTestCase, self).setUp(*args, **kwargs)
149+ self.options = FakeOptions()
150+
151+ def test_get_flags_long_arg(self):
152+ """Test that getting a flag works properly."""
153+ args = ['--foo', 'pathname']
154+ self.options.parseOptions(options=args)
155+ self.assertTrue(self.options['foo'])
156+
157+ def test_get_flags_short_arg(self):
158+ """Test that using the short version of a flag works."""
159+ args = ['-f', 'pathname']
160+ self.options.parseOptions(options=args)
161+ self.assertTrue(self.options['foo'])
162+
163+ def test_get_params_combined_arg(self):
164+ """Test that getting a parameter works properly."""
165+ expected = 'baz'
166+ args = ['--stuff=' + expected, 'pathname']
167+ self.options.parseOptions(options=args)
168+ self.assertEqual(expected, self.options['stuff'])
169+
170+ def test_get_params_missing_arg(self):
171+ """Test that passing no parameter argument fails correctly."""
172+ args = ['--stuff']
173+ self.assertRaises(UsageError, self.options.parseOptions, options=args)
174+
175+ def test_get_params_short_arg(self):
176+ """Test that using the short version of a parameter works."""
177+ expected = 'baz'
178+ args = ['-s', expected, 'pathname']
179+ self.options.parseOptions(options=args)
180+ self.assertEqual(expected, self.options['stuff'])
181+
182+ def test_get_params_split_arg(self):
183+ """Test that passing a parameter argument separately works."""
184+ expected = 'baz'
185+ args = ['--stuff', expected, 'pathname']
186+ self.options.parseOptions(options=args)
187+ self.assertEqual(expected, self.options['stuff'])
188+
189+ def test_unknown_option(self):
190+ """Test that passing an unknown option fails."""
191+ args = ['--unknown', 'pathname']
192+ self.assertRaises(UsageError, self.options.parseOptions, options=args)
193
194=== modified file 'ubuntuone/devtools/utils.py'
195--- ubuntuone/devtools/utils.py 2012-08-02 15:43:42 +0000
196+++ ubuntuone/devtools/utils.py 2012-08-13 21:10:25 +0000
197@@ -26,6 +26,8 @@
198 # files in the program, then also delete it here.
199 """Utilities for Ubuntu One developer tools."""
200
201+from __future__ import print_function, unicode_literals
202+
203 import getopt
204 import sys
205
206@@ -63,6 +65,7 @@
207 self.short_opts = ''
208 self.docs = {}
209 self.defaults = {}
210+ self.synonyms = {}
211 self.dispatch = {}
212
213 # Get the options and defaults
214@@ -76,6 +79,7 @@
215 self.docs.update(docs)
216 self.update(defaults)
217 self.defaults.update(defaults)
218+ self.synonyms.update(syns)
219 self.dispatch.update(dispatch)
220
221 # We use some camelcase names for trial compatibility here.
222@@ -97,11 +101,14 @@
223 else:
224 opt = opt[1:]
225
226- if (opt not in self.long_opts and
227- (len(opt) == 1 and opt not in self.short_opts)):
228+ if (opt not in self.synonyms.keys()):
229 raise UsageError('No such options: "%s"' % opt)
230
231- self.dispatch[opt](arg)
232+ opt = self.synonyms[opt]
233+ if self.defaults[opt] is False:
234+ self[opt] = True
235+ else:
236+ self.dispatch[opt](arg)
237
238 try:
239 self.parseArgs(*args)
240@@ -117,13 +124,13 @@
241 """Override to handle extra arguments specially."""
242 # pylint: enable=C0103
243
244- def _parse_arguments(self, has_default=False):
245+ def _parse_arguments(self, arg_type=None, has_default=False):
246 """Parse the arguments as either flags or parameters."""
247 long_opts, short_opts = [], ''
248- docs, defaults, dispatch = {}, {}, {}
249+ docs, defaults, syns, dispatch = {}, {}, {}, {}
250
251 _args = []
252- accumulate_list_attr(self.__class__, 'optFlags', _args)
253+ accumulate_list_attr(self.__class__, arg_type, _args)
254
255 for _arg in _args:
256 try:
257@@ -149,19 +156,25 @@
258 dispatch[l_opt] = lambda arg: True
259
260 defaults[l_opt] = default
261- long_opts.append(l_opt)
262+ if has_default:
263+ long_opts.append(l_opt + '=')
264+ else:
265+ long_opts.append(l_opt)
266+
267+ syns[l_opt] = l_opt
268 if s_opt is not None:
269 short_opts = short_opts + s_opt
270- docs[s_opt] = docs[l_opt]
271- dispatch[s_opt] = dispatch[l_opt]
272- defaults[s_opt] = defaults[l_opt]
273+ if has_default:
274+ short_opts = short_opts + ':'
275+ syns[s_opt] = l_opt
276
277- return long_opts, short_opts, docs, defaults, None, dispatch
278+ return long_opts, short_opts, docs, defaults, syns, dispatch
279
280 def _get_flags(self):
281 """Get the flag options."""
282- return self._parse_arguments(has_default=False)
283+ return self._parse_arguments(arg_type='optFlags', has_default=False)
284
285 def _get_params(self):
286 """Get the parameters options."""
287- return self._parse_arguments(has_default=True)
288+ return self._parse_arguments(arg_type='optParameters',
289+ has_default=True)

Subscribers

People subscribed via source and target branches

to all changes: