Merge lp:~thomir-deactivatedaccount/autopilot/add-launch-command-args into lp:autopilot
- add-launch-command-args
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Thomi Richards |
Approved revision: | 202 |
Merged at revision: | 199 |
Proposed branch: | lp:~thomir-deactivatedaccount/autopilot/add-launch-command-args |
Merge into: | lp:autopilot |
Diff against target: |
460 lines (+318/-86) 3 files modified
autopilot/__init__.py (+82/-0) autopilot/tests/unit/test_command_line_args.py (+234/-0) bin/autopilot (+2/-86) |
To merge this branch: | bzr merge lp:~thomir-deactivatedaccount/autopilot/add-launch-command-args |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Thomi Richards (community) | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email:
|
This proposal supersedes a proposal from 2013-05-06.
Commit message
Pass additional arguments to application being launched.
Description of the change
This branch fixes autopilot so you can run:
autopilot launch gnome-control-
and the "credentals" argument will be passed to the application launched. In order to do this, I moved the parse_arguments code into the autopilot module, and added a full suite of unit tests to ensure it works as we expect.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:202
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Thomi Richards (thomir-deactivatedaccount) : | # |
Preview Diff
1 | === modified file 'autopilot/__init__.py' |
2 | --- autopilot/__init__.py 2013-04-23 04:15:54 +0000 |
3 | +++ autopilot/__init__.py 2013-05-06 23:31:25 +0000 |
4 | @@ -17,6 +17,7 @@ |
5 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
6 | # |
7 | |
8 | +from argparse import ArgumentParser, REMAINDER |
9 | |
10 | version = '1.3' |
11 | |
12 | @@ -31,3 +32,84 @@ |
13 | + original_exception.message |
14 | ) |
15 | self.original_exception = original_exception |
16 | + |
17 | + |
18 | +def parse_arguments(argv=None): |
19 | + """Parse command-line arguments, and return an argparse arguments |
20 | + object. |
21 | + """ |
22 | + parser = ArgumentParser(description="Autopilot test tool.") |
23 | + subparsers = parser.add_subparsers(help='Run modes', dest="mode") |
24 | + |
25 | + parser_run = subparsers.add_parser('run', help="Run autopilot tests") |
26 | + parser_run.add_argument('-o', "--output", required=False, |
27 | + help='Write test result report to file.\ |
28 | + Defaults to stdout.\ |
29 | + If given a directory instead of a file will \ |
30 | + write to a file in that directory named: \ |
31 | + <hostname>_<dd.mm.yyy_HHMMSS>.log') |
32 | + parser_run.add_argument('-f', "--format", choices=['text', 'xml'], |
33 | + default='text', |
34 | + required=False, |
35 | + help='Specify desired output format. \ |
36 | + Default is "text".') |
37 | + parser_run.add_argument('-r', '--record', action='store_true', |
38 | + default=False, required=False, |
39 | + help="Record failing tests. Required \ |
40 | + 'recordmydesktop' app to be installed.\ |
41 | + Videos are stored in /tmp/autopilot.") |
42 | + parser_run.add_argument("-rd", "--record-directory", required=False, |
43 | + default="/tmp/autopilot", type=str, |
44 | + help="Directory to put recorded tests \ |
45 | + (only if -r) specified.") |
46 | + parser_run.add_argument('-v', '--verbose', default=False, required=False, |
47 | + action='count', |
48 | + help="If set, autopilot will output test log data \ |
49 | + to stderr during a test run. Set twice to also log \ |
50 | + data useful for debugging autopilot itself.") |
51 | + parser_run.add_argument("suite", nargs="+", |
52 | + help="Specify test suite(s) to run.") |
53 | + |
54 | + parser_list = subparsers.add_parser('list', help="List autopilot tests") |
55 | + parser_list.add_argument("-ro", "--run-order", required=False, default=False, |
56 | + action="store_true", |
57 | + help="List tests in run order, rather than alphabetical \ |
58 | + order (the default).") |
59 | + parser_list.add_argument("suite", nargs="+", |
60 | + help="Specify test suite(s) to run.") |
61 | + |
62 | + if have_vis(): |
63 | + parser_vis = subparsers.add_parser('vis', |
64 | + help="Open the Autopilot visualiser tool") |
65 | + parser_vis.add_argument('-v', '--verbose', required=False, default=False, |
66 | + action='count', help="Show autopilot log messages. \ |
67 | + Set twice to also log data useful for debugging \ |
68 | + autopilot itself.") |
69 | + |
70 | + parser_launch = subparsers.add_parser('launch', |
71 | + help="Launch an application with introspection enabled") |
72 | + parser_launch.add_argument('-i', '--interface', |
73 | + choices=('Gtk', 'Qt', 'Auto'), default='Auto', |
74 | + help="Specify which introspection interface to load. \ |
75 | + The default ('Auto') uses ldd to try and detect which \ |
76 | + interface to load.") |
77 | + parser_launch.add_argument('-v', '--verbose', required=False, default=False, |
78 | + action='count', help="Show autopilot log messages. \ |
79 | + Set twice to also log data useful for debugging \ |
80 | + autopilot itself.") |
81 | + parser_launch.add_argument('application', nargs=REMAINDER, type=str, |
82 | + help="The application to launch. Can be a full path, \ |
83 | + or just an application name (in which case Autopilot \ |
84 | + will search for it in $PATH).") |
85 | + args = parser.parse_args(args=argv) |
86 | + |
87 | + return args |
88 | + |
89 | + |
90 | +def have_vis(): |
91 | + """Return true if the vis package is installed.""" |
92 | + try: |
93 | + from autopilot.vis import vis_main |
94 | + return True |
95 | + except ImportError: |
96 | + return False |
97 | |
98 | === added file 'autopilot/tests/unit/test_command_line_args.py' |
99 | --- autopilot/tests/unit/test_command_line_args.py 1970-01-01 00:00:00 +0000 |
100 | +++ autopilot/tests/unit/test_command_line_args.py 2013-05-06 23:31:25 +0000 |
101 | @@ -0,0 +1,234 @@ |
102 | +#!/usr/bin/env python |
103 | +# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
104 | +# |
105 | +# Autopilot Functional Test Tool |
106 | +# Copyright (C) 2012-2013 Canonical |
107 | +# |
108 | +# This program is free software: you can redistribute it and/or modify |
109 | +# it under the terms of the GNU General Public License as published by |
110 | +# the Free Software Foundation, either version 3 of the License, or |
111 | +# (at your option) any later version. |
112 | +# |
113 | +# This program is distributed in the hope that it will be useful, |
114 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
115 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
116 | +# GNU General Public License for more details. |
117 | +# |
118 | +# You should have received a copy of the GNU General Public License |
119 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. |
120 | +# |
121 | + |
122 | + |
123 | +"Unit tests for the command line parser in autopilot." |
124 | + |
125 | + |
126 | +from mock import patch |
127 | +from StringIO import StringIO |
128 | +from testtools import TestCase |
129 | +from testtools.matchers import Equals |
130 | +from unittest import expectedFailure |
131 | + |
132 | +from autopilot import parse_arguments |
133 | + |
134 | + |
135 | +class CommandLineArgsTests(TestCase): |
136 | + |
137 | + def parse_args(self, args): |
138 | + if isinstance(args, basestring): |
139 | + args = args.split() |
140 | + try: |
141 | + return parse_arguments(args) |
142 | + except SystemExit as e: |
143 | + self.fail("Caught exception: %r" % e) |
144 | + |
145 | + def test_launch_command_accepts_application(self): |
146 | + args = self.parse_args("launch app") |
147 | + self.assertThat(args.mode, Equals("launch")) |
148 | + |
149 | + def test_launch_command_has_correct_default_interface(self): |
150 | + args = self.parse_args("launch app") |
151 | + self.assertThat(args.interface, Equals("Auto")) |
152 | + |
153 | + def test_launch_command_can_specify_Qt_interface(self): |
154 | + args = self.parse_args("launch -i Qt app") |
155 | + self.assertThat(args.interface, Equals("Qt")) |
156 | + |
157 | + def test_launch_command_can_specify_Gtk_interface(self): |
158 | + args = self.parse_args("launch -i Gtk app") |
159 | + self.assertThat(args.interface, Equals("Gtk")) |
160 | + |
161 | + @patch('sys.stderr', new=StringIO()) |
162 | + @expectedFailure |
163 | + def test_launch_command_fails_on_unknown_interface(self): |
164 | + self.parse_args("launch -i unknown app") |
165 | + |
166 | + def test_launch_command_has_correct_default_verbosity(self): |
167 | + args = self.parse_args("launch app") |
168 | + self.assertThat(args.verbose, Equals(False)) |
169 | + |
170 | + def test_launch_command_can_specify_verbosity(self): |
171 | + args = self.parse_args("launch -v app") |
172 | + self.assertThat(args.verbose, Equals(1)) |
173 | + |
174 | + def test_launch_command_can_specify_extra_verbosity(self): |
175 | + args = self.parse_args("launch -vv app") |
176 | + self.assertThat(args.verbose, Equals(2)) |
177 | + args = self.parse_args("launch -v -v app") |
178 | + self.assertThat(args.verbose, Equals(2)) |
179 | + |
180 | + def test_launch_command_stores_application(self): |
181 | + args = self.parse_args("launch app") |
182 | + self.assertThat(args.application, Equals(["app"])) |
183 | + |
184 | + def test_launch_command_stores_application_with_args(self): |
185 | + args = self.parse_args("launch app arg1 arg2") |
186 | + self.assertThat(args.application, Equals(["app", "arg1", "arg2"])) |
187 | + |
188 | + def test_launch_command_accepts_different_app_arg_formats(self): |
189 | + args = self.parse_args("launch app -s --long --key=val arg1 arg2") |
190 | + self.assertThat(args.application, |
191 | + Equals(["app", "-s", "--long", "--key=val", "arg1", "arg2"])) |
192 | + |
193 | + @patch('autopilot.have_vis', new=lambda: True) |
194 | + def test_vis_present_when_vis_module_installed(self): |
195 | + args = self.parse_args('vis') |
196 | + self.assertThat(args.mode, Equals("vis")) |
197 | + |
198 | + @patch('autopilot.have_vis', new=lambda: False) |
199 | + @patch('sys.stderr', new=StringIO()) |
200 | + @expectedFailure |
201 | + def test_vis_not_present_when_vis_module_not_installed(self): |
202 | + self.parse_args('vis') |
203 | + |
204 | + @patch('autopilot.have_vis', new=lambda: True) |
205 | + def test_vis_default_verbosity(self): |
206 | + args = self.parse_args('vis') |
207 | + self.assertThat(args.verbose, Equals(False)) |
208 | + |
209 | + @patch('autopilot.have_vis', new=lambda: True) |
210 | + def test_vis_single_verbosity(self): |
211 | + args = self.parse_args('vis -v') |
212 | + self.assertThat(args.verbose, Equals(1)) |
213 | + |
214 | + @patch('autopilot.have_vis', new=lambda: True) |
215 | + def test_vis_double_verbosity(self): |
216 | + args = self.parse_args('vis -vv') |
217 | + self.assertThat(args.verbose, Equals(2)) |
218 | + args = self.parse_args('vis -v -v') |
219 | + self.assertThat(args.verbose, Equals(2)) |
220 | + |
221 | + def test_list_mode(self): |
222 | + args = self.parse_args('list foo') |
223 | + self.assertThat(args.mode, Equals("list")) |
224 | + |
225 | + def test_list_mode_accepts_suite_name(self): |
226 | + args = self.parse_args('list foo') |
227 | + self.assertThat(args.suite, Equals(["foo"])) |
228 | + |
229 | + def test_list_mode_accepts_many_suite_names(self): |
230 | + args = self.parse_args('list foo bar baz') |
231 | + self.assertThat(args.suite, Equals(["foo", "bar", "baz"])) |
232 | + |
233 | + def test_list_run_order_long_option(self): |
234 | + args = self.parse_args('list --run-order foo') |
235 | + self.assertThat(args.run_order, Equals(True)) |
236 | + |
237 | + def test_list_run_order_short_option(self): |
238 | + args = self.parse_args('list -ro foo') |
239 | + self.assertThat(args.run_order, Equals(True)) |
240 | + |
241 | + def test_list_no_run_order(self): |
242 | + args = self.parse_args('list foo') |
243 | + self.assertThat(args.run_order, Equals(False)) |
244 | + |
245 | + def test_run_mode(self): |
246 | + args = self.parse_args('run foo') |
247 | + self.assertThat(args.mode, Equals("run")) |
248 | + |
249 | + def test_run_mode_accepts_suite_name(self): |
250 | + args = self.parse_args('run foo') |
251 | + self.assertThat(args.suite, Equals(["foo"])) |
252 | + |
253 | + def test_run_mode_accepts_many_suite_names(self): |
254 | + args = self.parse_args('run foo bar baz') |
255 | + self.assertThat(args.suite, Equals(["foo", "bar", "baz"])) |
256 | + |
257 | + def test_run_command_default_output(self): |
258 | + args = self.parse_args('run foo') |
259 | + self.assertThat(args.output, Equals(None)) |
260 | + |
261 | + def test_run_command_path_output_short(self): |
262 | + args = self.parse_args('run -o /path/to/file foo') |
263 | + self.assertThat(args.output, Equals("/path/to/file")) |
264 | + |
265 | + def test_run_command_path_output_long(self): |
266 | + args = self.parse_args('run --output ../file foo') |
267 | + self.assertThat(args.output, Equals("../file")) |
268 | + |
269 | + def test_run_command_default_format(self): |
270 | + args = self.parse_args('run foo') |
271 | + self.assertThat(args.format, Equals("text")) |
272 | + |
273 | + def test_run_command_text_format_short_version(self): |
274 | + args = self.parse_args('run -f text foo') |
275 | + self.assertThat(args.format, Equals("text")) |
276 | + |
277 | + def test_run_command_text_format_long_version(self): |
278 | + args = self.parse_args('run --format text foo') |
279 | + self.assertThat(args.format, Equals("text")) |
280 | + |
281 | + def test_run_command_xml_format_short_version(self): |
282 | + args = self.parse_args('run -f xml foo') |
283 | + self.assertThat(args.format, Equals("xml")) |
284 | + |
285 | + def test_run_command_xml_format_long_version(self): |
286 | + args = self.parse_args('run --format xml foo') |
287 | + self.assertThat(args.format, Equals("xml")) |
288 | + |
289 | + @patch('sys.stderr', new=StringIO()) |
290 | + @expectedFailure |
291 | + def test_run_command_unknown_format_short_version(self): |
292 | + self.parse_args('run -f unknown foo') |
293 | + |
294 | + @patch('sys.stderr', new=StringIO()) |
295 | + @expectedFailure |
296 | + def test_run_command_unknown_format_long_version(self): |
297 | + self.parse_args('run --format unknown foo') |
298 | + |
299 | + def test_run_command_record_flag_default(self): |
300 | + args = self.parse_args("run foo") |
301 | + self.assertThat(args.record, Equals(False)) |
302 | + |
303 | + def test_run_command_record_flag_short(self): |
304 | + args = self.parse_args("run -r foo") |
305 | + self.assertThat(args.record, Equals(True)) |
306 | + |
307 | + def test_run_command_record_flag_long(self): |
308 | + args = self.parse_args("run --record foo") |
309 | + self.assertThat(args.record, Equals(True)) |
310 | + |
311 | + def test_run_command_record_dir_flag_default(self): |
312 | + args = self.parse_args("run foo") |
313 | + self.assertThat(args.record_directory, Equals("/tmp/autopilot")) |
314 | + |
315 | + def test_run_command_record_dir_flag_short(self): |
316 | + args = self.parse_args("run -rd /path/to/dir foo") |
317 | + self.assertThat(args.record_directory, Equals("/path/to/dir")) |
318 | + |
319 | + def test_run_command_record_dir_flag_long(self): |
320 | + args = self.parse_args("run --record-directory /path/to/dir foo") |
321 | + self.assertThat(args.record_directory, Equals("/path/to/dir")) |
322 | + |
323 | + def test_run_default_verbosity(self): |
324 | + args = self.parse_args('run foo') |
325 | + self.assertThat(args.verbose, Equals(False)) |
326 | + |
327 | + def test_run_single_verbosity(self): |
328 | + args = self.parse_args('run -v foo') |
329 | + self.assertThat(args.verbose, Equals(1)) |
330 | + |
331 | + def test_run_double_verbosity(self): |
332 | + args = self.parse_args('run -vv foo') |
333 | + self.assertThat(args.verbose, Equals(2)) |
334 | + args = self.parse_args('run -v -v foo') |
335 | + self.assertThat(args.verbose, Equals(2)) |
336 | |
337 | === modified file 'bin/autopilot' |
338 | --- bin/autopilot 2013-05-02 22:24:57 +0000 |
339 | +++ bin/autopilot 2013-05-06 23:31:25 +0000 |
340 | @@ -39,8 +39,6 @@ |
341 | import subprocess |
342 | from testtools import iterate_tests |
343 | from testtools import TextTestResult |
344 | -from textwrap import dedent |
345 | -from argparse import ArgumentParser |
346 | from unittest.loader import TestLoader |
347 | from unittest import TestSuite |
348 | |
349 | @@ -48,80 +46,6 @@ |
350 | _output_stream=None |
351 | |
352 | |
353 | -def parse_arguments(): |
354 | - """Parse command-line arguments, and return an argparse arguments |
355 | - object. |
356 | - """ |
357 | - parser = ArgumentParser(description=dedent("""\ |
358 | - Autopilot test tool. |
359 | - """)) |
360 | - subparsers = parser.add_subparsers(help='Run modes', dest="mode") |
361 | - |
362 | - parser_run = subparsers.add_parser('run', help="Run autopilot tests") |
363 | - parser_run.add_argument('-o', "--output", required=False, |
364 | - help='Write test result report to file.\ |
365 | - Defaults to stdout.\ |
366 | - If given a directory instead of a file will \ |
367 | - write to a file in that directory named: \ |
368 | - <hostname>_<dd.mm.yyy_HHMMSS>.log') |
369 | - parser_run.add_argument('-f', "--format", choices=['text', 'xml'], |
370 | - default='text', |
371 | - required=False, |
372 | - help='Specify desired output format. \ |
373 | - Default is "text".') |
374 | - parser_run.add_argument('-r', '--record', action='store_true', |
375 | - default=False, required=False, |
376 | - help="Record failing tests. Required \ |
377 | - 'recordmydesktop' app to be installed.\ |
378 | - Videos are stored in /tmp/autopilot.") |
379 | - parser_run.add_argument("-rd", "--record-directory", required=False, |
380 | - default="/tmp/autopilot", type=str, |
381 | - help="Directory to put recorded tests \ |
382 | - (only if -r) specified.") |
383 | - parser_run.add_argument('-v', '--verbose', default=False, required=False, |
384 | - action='count', |
385 | - help="If set, autopilot will output test log data \ |
386 | - to stderr during a test run. Set twice to also log \ |
387 | - data useful for debugging autopilot itself.") |
388 | - parser_run.add_argument("suite", nargs="+", |
389 | - help="Specify test suite(s) to run.") |
390 | - |
391 | - parser_list = subparsers.add_parser('list', help="List autopilot tests") |
392 | - parser_list.add_argument("-ro", "--run-order", required=False, default=False, |
393 | - action="store_true", |
394 | - help="List tests in run order, rather than alphabetical \ |
395 | - order (the default).") |
396 | - parser_list.add_argument("suite", nargs="+", |
397 | - help="Specify test suite(s) to run.") |
398 | - |
399 | - if have_vis(): |
400 | - parser_vis = subparsers.add_parser('vis', |
401 | - help="Open the Autopilot visualiser tool") |
402 | - parser_vis.add_argument('-v', '--verbose', required=False, default=False, |
403 | - action='count', help="Show autopilot log messages. \ |
404 | - Set twice to also log data useful for debugging \ |
405 | - autopilot itself.") |
406 | - |
407 | - parser_launch = subparsers.add_parser('launch', |
408 | - help="Launch an application with introspection enabled") |
409 | - parser_launch.add_argument('-i', '--interface', |
410 | - choices=('Gtk', 'Qt', 'Auto'), default='Auto', |
411 | - help="Specify which introspection interface to load. \ |
412 | - The default ('Auto') uses ldd to try and detect which \ |
413 | - interface to load.") |
414 | - parser_launch.add_argument('-v', '--verbose', required=False, default=False, |
415 | - action='count', help="Show autopilot log messages. \ |
416 | - Set twice to also log data useful for debugging \ |
417 | - autopilot itself.") |
418 | - parser_launch.add_argument('application', nargs=1, type=str, |
419 | - help="The application to launch. Can be a full path, \ |
420 | - or just an application name (in which case Autopilot \ |
421 | - will search for it in $PATH).") |
422 | - args = parser.parse_args() |
423 | - |
424 | - return args |
425 | - |
426 | - |
427 | def list_tests(args): |
428 | """Print a list of tests we find inside autopilot.tests.""" |
429 | num_tests = 0 |
430 | @@ -341,21 +265,12 @@ |
431 | exit(1) |
432 | |
433 | try: |
434 | - launch_application(launcher, app_name, capture_output=False) |
435 | + launch_application(launcher, *args.application, capture_output=False) |
436 | except RuntimeError as e: |
437 | print "Error: " + e.message |
438 | exit(1) |
439 | |
440 | |
441 | -def have_vis(): |
442 | - """Return true if the vis package is installed.""" |
443 | - try: |
444 | - from autopilot.vis import vis_main |
445 | - return True |
446 | - except ImportError: |
447 | - return False |
448 | - |
449 | - |
450 | def run_vis(args): |
451 | setup_logging(args.verbose) |
452 | # importing this requires that DISPLAY is set. Since we don't always want |
453 | @@ -374,6 +289,7 @@ |
454 | |
455 | |
456 | def main(): |
457 | + from autopilot import parse_arguments |
458 | args = parse_arguments() |
459 | if args.mode == 'list': |
460 | list_tests(args) |
FAILED: Continuous integration, rev:202 /code.launchpad .net/~thomir/ autopilot/ add-launch- command- args/+merge/ 162684/ +edit-commit- message
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http:// jenkins. qa.ubuntu. com/job/ autopilot- ci/77/ jenkins. qa.ubuntu. com/job/ autopilot- raring- amd64-ci/ 77 jenkins. qa.ubuntu. com/job/ autopilot- raring- armhf-ci/ 76 jenkins. qa.ubuntu. com/job/ autopilot- saucy-amd64- ci/5 jenkins. qa.ubuntu. com/job/ autopilot- saucy-armhf- ci/5
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins: 8080/job/ autopilot- ci/77/rebuild
http://