Merge lp:~benji/lpsetup/bug-1017973-add-smoke-tests into lp:lpsetup

Proposed by Benji York
Status: Merged
Approved by: Benji York
Approved revision: 39
Merged at revision: 35
Proposed branch: lp:~benji/lpsetup/bug-1017973-add-smoke-tests
Merge into: lp:lpsetup
Diff against target: 153 lines (+49/-24)
7 files modified
lpsetup/argparser.py (+1/-4)
lpsetup/cli.py (+21/-10)
lpsetup/tests/subcommands/test_inithost.py (+0/-2)
lpsetup/tests/subcommands/test_install.py (+0/-2)
lpsetup/tests/subcommands/test_smoke.py (+21/-0)
lpsetup/tests/test_argparser.py (+3/-4)
setup.py (+3/-2)
To merge this branch: bzr merge lp:~benji/lpsetup/bug-1017973-add-smoke-tests
Reviewer Review Type Date Requested Status
Francesco Banconi (community) Approve
Review via email: mp+112141@code.launchpad.net

Commit message

add a basic smoke test for the subcommands

Description of the change

This branch adds a basic smoke test for the subcommands by running each with --help and asserting that no exceptions are raised and a non-error (zero) exit code is returned.

A little refactoring was required to get the tests to work, which was discussed with Francesco by way of mid-implementation call.

Lint: pocketlint reports no lint

Tests: the obvious test was added and I also tested the test by introducing SyntaxError and NameError in subcommand code and verified that the new test failed.

To post a comment you must log in.
Revision history for this message
Francesco Banconi (frankban) wrote :

Benji, the code looks good, and thanks for your changes to the previous weird exception handling in *StepsBasedSubcommand.handle*.

Just an observation:

54 + try:
55 + args = parser.parse_args(args)
56 + except SystemExit:
57 + return 0

Now the main function is consistent and just returns an error, an exit code or None, and that's great. However, in my opinion we should return the error or the exit code here too, otherwise lp-setup exits with 0 even if wrong arguments are provided. Something like::

    except SystemExit as err:
        return err # or err.code

review: Approve
Revision history for this message
Benji York (benji) wrote :

> Now the main function is consistent and just returns an error, an exit code or
> None, and that's great. However, in my opinion we should return the error or
> the exit code here too, otherwise lp-setup exits with 0 even if wrong
> arguments are provided. Something like::
>
> except SystemExit as err:
> return err # or err.code

Indeed! I have made that change (using err.code).

Revision history for this message
Brad Crittenden (bac) wrote :

There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.

Revision history for this message
Brad Crittenden (bac) wrote :

Attempt to merge into lp:lpsetup failed due to conflicts:

text conflict in lpsetup/tests/test_argparser.py

Revision history for this message
Brad Crittenden (bac) wrote :

The attempt to merge lp:~benji/lpsetup/bug-1017973-add-smoke-tests into lp:lpsetup failed. Below is the output from the failed tests.

nose.plugins.cover: ERROR: Coverage not available: unable to import coverage module
...............................usage: nosetests [-h] {subcmd,help} ...
nosetests: error: unrecognized arguments: --foo eggs
E...........................................
======================================================================
ERROR: test_failing_step (lpsetup.tests.test_argparser.StepsBasedSubCommandWithErrorsTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/var/cache/tarmac/lpsetup/trunk/lpsetup/tests/test_argparser.py", line 174, in test_failing_step
    self.parse_and_call_main('--foo eggs')
  File "/var/cache/tarmac/lpsetup/trunk/lpsetup/tests/utils.py", line 72, in parse_and_call_main
    namespace = self.parse(*args)
  File "/var/cache/tarmac/lpsetup/trunk/lpsetup/tests/utils.py", line 64, in parse
    namespace = self.parser.parse_args((self.sub_command_name,) + args)
  File "/var/cache/tarmac/lpsetup/trunk/lpsetup/argparser.py", line 157, in parse_args
    return super(ArgumentParser, self).parse_args(*args, **kwargs)
  File "/usr/lib/python2.7/argparse.py", line 1691, in parse_args
    self.error(msg % ' '.join(argv))
  File "/usr/lib/python2.7/argparse.py", line 2347, in error
    self.exit(2, _('%s: error: %s\n') % (self.prog, message))
  File "/usr/lib/python2.7/argparse.py", line 2335, in exit
    _sys.exit(status)
SystemExit: 2

----------------------------------------------------------------------
Ran 75 tests in 0.636s

FAILED (errors=1)

Revision history for this message
Brad Crittenden (bac) wrote :

There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lpsetup/argparser.py'
2--- lpsetup/argparser.py 2012-06-26 14:56:11 +0000
3+++ lpsetup/argparser.py 2012-06-26 18:36:19 +0000
4@@ -489,7 +489,4 @@
5 # Run the step using a dynamic dispatcher.
6 step_runner = getattr(
7 self, 'call_' + step_name, default_step_runner)
8- try:
9- step_runner(namespace, step, args)
10- except subprocess.CalledProcessError as err:
11- return err
12+ step_runner(namespace, step, args)
13
14=== modified file 'lpsetup/cli.py'
15--- lpsetup/cli.py 2012-06-22 20:50:41 +0000
16+++ lpsetup/cli.py 2012-06-26 18:36:19 +0000
17@@ -9,6 +9,7 @@
18 'main',
19 ]
20
21+import sys
22 from lpsetup import (
23 __doc__ as description,
24 argparser,
25@@ -24,17 +25,27 @@
26 version,
27 )
28
29-
30-def main():
31+subcommands = [
32+ ('install', install.SubCommand),
33+ ('inithost', inithost.SubCommand),
34+ ('get', get.SubCommand),
35+ ('update', update.SubCommand),
36+ ('lxc-install', lxcinstall.SubCommand),
37+ ('branch', branch.SubCommand),
38+ ('version', version.SubCommand),
39+ ]
40+
41+
42+def main(args=None):
43+ if args is None:
44+ args = sys.argv[1:]
45 parser = argparser.ArgumentParser(description=description)
46- parser.register_subcommand('install', install.SubCommand)
47- parser.register_subcommand('inithost', inithost.SubCommand)
48- parser.register_subcommand('get', get.SubCommand)
49- parser.register_subcommand('update', update.SubCommand)
50- parser.register_subcommand('lxc-install', lxcinstall.SubCommand)
51- parser.register_subcommand('branch', branch.SubCommand)
52- parser.register_subcommand('version', version.SubCommand)
53- args = parser.parse_args()
54+ for subcommand, callable in subcommands:
55+ parser.register_subcommand(subcommand, callable)
56+ try:
57+ args = parser.parse_args(args)
58+ except SystemExit as err:
59+ return err.code
60 try:
61 return args.main(args)
62 except (exceptions.ExecutionError, KeyboardInterrupt) as err:
63
64=== modified file 'lpsetup/tests/subcommands/test_inithost.py'
65--- lpsetup/tests/subcommands/test_inithost.py 2012-06-26 10:17:27 +0000
66+++ lpsetup/tests/subcommands/test_inithost.py 2012-06-26 18:36:19 +0000
67@@ -46,5 +46,3 @@
68 )
69 expected_steps = (initialize_step, setup_apt_step)
70 needs_root = True
71-
72-
73
74=== modified file 'lpsetup/tests/subcommands/test_install.py'
75--- lpsetup/tests/subcommands/test_install.py 2012-06-26 10:17:27 +0000
76+++ lpsetup/tests/subcommands/test_install.py 2012-06-26 18:36:19 +0000
77@@ -51,5 +51,3 @@
78 setup_launchpad_step,
79 )
80 needs_root = True
81-
82-
83
84=== added file 'lpsetup/tests/subcommands/test_smoke.py'
85--- lpsetup/tests/subcommands/test_smoke.py 1970-01-01 00:00:00 +0000
86+++ lpsetup/tests/subcommands/test_smoke.py 2012-06-26 18:36:19 +0000
87@@ -0,0 +1,21 @@
88+# Copyright 2012 Canonical Ltd. This software is licensed under the
89+# GNU Affero General Public License version 3 (see the file LICENSE).
90+
91+"""Smoke tests for the sub commands."""
92+
93+import unittest
94+
95+from lpsetup.cli import (
96+ main,
97+ subcommands,
98+ )
99+
100+
101+class SmokeTest(unittest.TestCase):
102+ """Tests which are intended to do a quick check for broken subcommands."""
103+
104+ def test_subcommand_smoke_via_help(self):
105+ # Perform a basic smoke test by running each subcommand's --help
106+ # function and verify that a non-error exit code is returned.
107+ for subcommand, callable in subcommands:
108+ self.assertEqual(main([subcommand, '--help']), 0)
109
110=== modified file 'lpsetup/tests/test_argparser.py'
111--- lpsetup/tests/test_argparser.py 2012-06-26 10:17:27 +0000
112+++ lpsetup/tests/test_argparser.py 2012-06-26 18:36:19 +0000
113@@ -4,6 +4,7 @@
114
115 """Tests for the argparser module."""
116
117+import subprocess
118 import unittest
119
120 from lpsetup import argparser
121@@ -169,10 +170,8 @@
122 def test_failing_step(self):
123 # Ensure the steps execution is stopped if a step raises
124 # `subprocess.CalledProcessError`.
125- with capture_output() as output:
126- error = self.parse_and_call_main('--foo', 'eggs')
127- self.assertEqual(1, error.returncode)
128- self.check_output(['step1 received eggs'], output)
129+ with self.assertRaises(subprocess.CalledProcessError):
130+ self.parse_and_call_main('--foo', 'eggs')
131
132
133 class DynamicStepsBasedSubCommandTest(SubCommandTestMixin, unittest.TestCase):
134
135=== modified file 'setup.py'
136--- setup.py 2012-06-25 21:17:38 +0000
137+++ setup.py 2012-06-26 18:36:19 +0000
138@@ -22,12 +22,13 @@
139 data_files = []
140 for dirpath, dirnames, filenames in os.walk(project_name):
141 for i, dirname in enumerate(dirnames):
142- if dirname.startswith('.'): del dirnames[i]
143+ if dirname.startswith('.'):
144+ del dirnames[i]
145 if '__init__.py' in filenames:
146 continue
147 elif filenames:
148 for f in filenames:
149- data_files.append(os.path.join(dirpath[len(project_name)+1:], f))
150+ data_files.append(os.path.join(dirpath[len(project_name) + 1:], f))
151
152 project = __import__(project_name)
153 long_description = open(os.path.join(root_dir, 'README.rst')).read()

Subscribers

People subscribed via source and target branches

to all changes: