Merge ~sylvain-pineau/checkbox-ng:inline_shellcheck_flake8 into checkbox-ng:master

Proposed by Sylvain Pineau
Status: Merged
Approved by: Sylvain Pineau
Approved revision: 8ed75ea6665e75a1f98f0e2cb6d5cface0ec41af
Merged at revision: ac158658dd61cecfde0c89c0e2c5fb5accad2c40
Proposed branch: ~sylvain-pineau/checkbox-ng:inline_shellcheck_flake8
Merge into: checkbox-ng:master
Diff against target: 195 lines (+136/-9)
1 file modified
plainbox/provider_manager.py (+136/-9)
Reviewer Review Type Date Requested Status
Jonathan Cave (community) Approve
Sylvain Pineau (community) Needs Resubmitting
Review via email: mp+387256@code.launchpad.net

Description of the change

Extend the existing manage.py test command by adding flake8 for python3 scripts and support for inline command shellcheck.

Sample output for p-p-c:

Ran 940 tests in 16.485s

FAILED (failures=367)

To post a comment you must log in.
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

I've added a subparser to run only a subset of the tests, so that we can work of fixing e.g shellcheck errors while still running the unit tests from PMR.

For instance:

./manage.py test -u

will only run the unit tests.
Default is still running all sort of tests.
But with the various options, we can easily modify our pmr hooks to run the tests we consider ready.

review: Needs Resubmitting
Revision history for this message
Jonathan Cave (jocave) wrote :

LGTM

I was wondering whether to suggest allowing combinations of multiple flags e.g. manage.py test -u -s -f, but running multiple invocations of manaage.py has the same effect so probably not worth it.

review: Approve
Revision history for this message
Sylvain Pineau (sylvain-pineau) wrote :

Exactly. Moreover the end goal is to run it w/o any args in pmr.

As an interim hook, invoking them one by one is acceptable IHMO.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/plainbox/provider_manager.py b/plainbox/provider_manager.py
2index 319cc90..58748ae 100644
3--- a/plainbox/provider_manager.py
4+++ b/plainbox/provider_manager.py
5@@ -54,6 +54,7 @@ from plainbox.impl.providers.special import get_categories
6 from plainbox.impl.providers.special import get_manifest
7 from plainbox.impl.providers.v1 import InsecureProvider1PlugInCollection
8 from plainbox.impl.providers.v1 import get_user_PROVIDERPATH_entry
9+from plainbox.impl.resource import Resource
10 from plainbox.impl.secure.config import Unset
11 from plainbox.impl.secure.config import ValidationError \
12 as ConfigValidationError
13@@ -1326,6 +1327,29 @@ class PackagingCommand(ManageCommand):
14 driver.modify_packaging_tree()
15
16
17+class InlineShellcheckTests(unittest.TestCase):
18+ """
19+ Holder of inline pxu job commands shellcheck test cases.
20+
21+ If candidates for shellcheck testing are found when TestCommand is invoked,
22+ this class will have member functions monkey patched in to place that
23+ represent an individual test case for each pxu file job command.
24+ """
25+ pass
26+
27+
28+def create_inline_shellcheck_test(command):
29+ """Creates the target for the monkey patched methods in ShellcheckTests"""
30+
31+ def run_inline_shellcheck(self):
32+ result = subprocess.run(
33+ ['shellcheck', '-', '--shell=bash'],
34+ input=command,
35+ encoding='ascii')
36+ self.assertEqual(result.returncode, 0)
37+ return run_inline_shellcheck
38+
39+
40 class ShellcheckTests(unittest.TestCase):
41 """
42 Holder of shellcheck test cases.
43@@ -1337,7 +1361,7 @@ class ShellcheckTests(unittest.TestCase):
44 pass
45
46
47-def create_test(shellfile):
48+def create_shellcheck_test(shellfile):
49 """Creates the target for the monkey patched methods in ShellcheckTests"""
50
51 def run_shellcheck(self):
52@@ -1346,6 +1370,26 @@ def create_test(shellfile):
53 return run_shellcheck
54
55
56+class Flake8Tests(unittest.TestCase):
57+ """
58+ Holder of Flake8 test cases.
59+
60+ If candidates for Flake8 testing are found when TestCommand is invoked,
61+ this class will have member functions monkey patched in to place that
62+ represent an individual test case for each file.
63+ """
64+ pass
65+
66+
67+def create_flake8_test(pyfile):
68+ """Creates the target for the monkey patched methods in Flake8Tests"""
69+
70+ def run_flake8(self):
71+ result = subprocess.run(['flake8', pyfile])
72+ self.assertEqual(result.returncode, 0)
73+ return run_flake8
74+
75+
76 class TestCommand(ManageCommand):
77 """run tests defined for this provider"""
78
79@@ -1360,26 +1404,109 @@ class TestCommand(ManageCommand):
80 return os.path.join(self.definition.location, 'bin')
81
82 def register_parser(self, subparsers):
83- self.add_subcommand(subparsers)
84+ """
85+ Overridden method of CommandBase.
86+
87+ :param subparsers:
88+ The argparse subparsers objects in which command line argument
89+ specification should be created.
90+
91+ This method is invoked by the command line handling code to register
92+ arguments specific to this sub-command. It must also register itself as
93+ the command class with the ``command`` default.
94+ """
95+ parser = self.add_subcommand(subparsers)
96+ group = parser.add_argument_group(title=_("test options"))
97+ group.add_argument(
98+ '-i', '--inline', action='store_true',
99+ help=_("Only job inline commands"))
100+ group.add_argument(
101+ '-f', '--flake8', action='store_true',
102+ help=_("Only Flake8"))
103+ group.add_argument(
104+ '-s', '--shellcheck', action='store_true',
105+ help=_("Only ShellCheck"))
106+ group.add_argument(
107+ '-u', '--unittest', action='store_true',
108+ help=_("Only unittest from tests/ dir"))
109
110 def invoked(self, ns):
111 sys.path.insert(0, self.scripts_dir)
112 runner = TextTestRunner(verbosity=2)
113+ provider = self.get_provider()
114
115 # create unittest for each bin/*.sh file
116 for file in glob.glob(self.scripts_dir + "/*.sh"):
117- test_method = create_test(file)
118- test_method.__name__ = 'test_shellcheck_{}'.format(
119- os.path.splitext(file)[0])
120+ test_method = create_shellcheck_test(file)
121+ test_method.__name__ = 'test_shellcheck_{}'.format(file)
122 setattr(ShellcheckTests, test_method.__name__, test_method)
123+
124 shellcheck_suite = defaultTestLoader.loadTestsFromTestCase(
125 ShellcheckTests)
126
127- # find tests defined in tests/
128- tests_dir_suite = defaultTestLoader.discover(self.tests_dir)
129+ # create unittest for each bin/*.py file
130+ for file in glob.glob(self.scripts_dir + "/*.py"):
131+ test_method = create_flake8_test(file)
132+ test_method.__name__ = 'test_flake8_{}'.format(file)
133+ setattr(Flake8Tests, test_method.__name__, test_method)
134+
135+ flake8_suite = defaultTestLoader.loadTestsFromTestCase(
136+ Flake8Tests)
137
138- result = runner.run(unittest.TestSuite(
139- [shellcheck_suite, tests_dir_suite]))
140+ # create unittest for each job unit command
141+ unit_list = provider.unit_list
142+ for unit in unit_list:
143+ if unit.Meta.name == 'template':
144+ unit._fake_resources = True
145+ accessed_parameters = unit.get_accessed_parameters(
146+ force=True, template_engine=unit.template_engine)
147+ resource = Resource({
148+ key: key.upper()
149+ for key in set(
150+ itertools.chain(*accessed_parameters.values()))
151+ })
152+ command = unit.instantiate_one(resource).command
153+ if command:
154+ test_method = create_inline_shellcheck_test(command)
155+ test_method.__name__ = 'test_job_command_{}_{}'.format(
156+ unit.origin.relative_to(self.definition.location),
157+ unit.partial_id)
158+ setattr(
159+ InlineShellcheckTests,
160+ test_method.__name__, test_method)
161+ elif unit.Meta.name == 'job' and unit.command:
162+ test_method = create_inline_shellcheck_test(unit.command)
163+ test_method.__name__ = 'test_job_command_{}_{}'.format(
164+ unit.origin.relative_to(self.definition.location),
165+ unit.partial_id)
166+ setattr(
167+ InlineShellcheckTests,
168+ test_method.__name__, test_method)
169+
170+ inline_shellcheck_suite = defaultTestLoader.loadTestsFromTestCase(
171+ InlineShellcheckTests)
172+
173+ # find tests defined in tests/
174+ if os.path.exists(self.tests_dir):
175+ tests_dir_suite = defaultTestLoader.discover(self.tests_dir)
176+ else:
177+ tests_dir_suite = unittest.TestSuite()
178+
179+ if ns.inline:
180+ result = runner.run(unittest.TestSuite([inline_shellcheck_suite]))
181+ elif ns.flake8:
182+ result = runner.run(unittest.TestSuite([flake8_suite]))
183+ elif ns.unittest:
184+ result = runner.run(unittest.TestSuite([tests_dir_suite]))
185+ elif ns.shellcheck:
186+ result = runner.run(unittest.TestSuite([shellcheck_suite]))
187+ else:
188+ result = runner.run(unittest.TestSuite([
189+ inline_shellcheck_suite,
190+ shellcheck_suite,
191+ flake8_suite,
192+ tests_dir_suite
193+ ]))
194 if not result.wasSuccessful():
195 return 1
196

Subscribers

People subscribed via source and target branches