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
diff --git a/plainbox/provider_manager.py b/plainbox/provider_manager.py
index 319cc90..58748ae 100644
--- a/plainbox/provider_manager.py
+++ b/plainbox/provider_manager.py
@@ -54,6 +54,7 @@ from plainbox.impl.providers.special import get_categories
54from plainbox.impl.providers.special import get_manifest54from plainbox.impl.providers.special import get_manifest
55from plainbox.impl.providers.v1 import InsecureProvider1PlugInCollection55from plainbox.impl.providers.v1 import InsecureProvider1PlugInCollection
56from plainbox.impl.providers.v1 import get_user_PROVIDERPATH_entry56from plainbox.impl.providers.v1 import get_user_PROVIDERPATH_entry
57from plainbox.impl.resource import Resource
57from plainbox.impl.secure.config import Unset58from plainbox.impl.secure.config import Unset
58from plainbox.impl.secure.config import ValidationError \59from plainbox.impl.secure.config import ValidationError \
59 as ConfigValidationError60 as ConfigValidationError
@@ -1326,6 +1327,29 @@ class PackagingCommand(ManageCommand):
1326 driver.modify_packaging_tree()1327 driver.modify_packaging_tree()
13271328
13281329
1330class InlineShellcheckTests(unittest.TestCase):
1331 """
1332 Holder of inline pxu job commands shellcheck test cases.
1333
1334 If candidates for shellcheck testing are found when TestCommand is invoked,
1335 this class will have member functions monkey patched in to place that
1336 represent an individual test case for each pxu file job command.
1337 """
1338 pass
1339
1340
1341def create_inline_shellcheck_test(command):
1342 """Creates the target for the monkey patched methods in ShellcheckTests"""
1343
1344 def run_inline_shellcheck(self):
1345 result = subprocess.run(
1346 ['shellcheck', '-', '--shell=bash'],
1347 input=command,
1348 encoding='ascii')
1349 self.assertEqual(result.returncode, 0)
1350 return run_inline_shellcheck
1351
1352
1329class ShellcheckTests(unittest.TestCase):1353class ShellcheckTests(unittest.TestCase):
1330 """1354 """
1331 Holder of shellcheck test cases.1355 Holder of shellcheck test cases.
@@ -1337,7 +1361,7 @@ class ShellcheckTests(unittest.TestCase):
1337 pass1361 pass
13381362
13391363
1340def create_test(shellfile):1364def create_shellcheck_test(shellfile):
1341 """Creates the target for the monkey patched methods in ShellcheckTests"""1365 """Creates the target for the monkey patched methods in ShellcheckTests"""
13421366
1343 def run_shellcheck(self):1367 def run_shellcheck(self):
@@ -1346,6 +1370,26 @@ def create_test(shellfile):
1346 return run_shellcheck1370 return run_shellcheck
13471371
13481372
1373class Flake8Tests(unittest.TestCase):
1374 """
1375 Holder of Flake8 test cases.
1376
1377 If candidates for Flake8 testing are found when TestCommand is invoked,
1378 this class will have member functions monkey patched in to place that
1379 represent an individual test case for each file.
1380 """
1381 pass
1382
1383
1384def create_flake8_test(pyfile):
1385 """Creates the target for the monkey patched methods in Flake8Tests"""
1386
1387 def run_flake8(self):
1388 result = subprocess.run(['flake8', pyfile])
1389 self.assertEqual(result.returncode, 0)
1390 return run_flake8
1391
1392
1349class TestCommand(ManageCommand):1393class TestCommand(ManageCommand):
1350 """run tests defined for this provider"""1394 """run tests defined for this provider"""
13511395
@@ -1360,26 +1404,109 @@ class TestCommand(ManageCommand):
1360 return os.path.join(self.definition.location, 'bin')1404 return os.path.join(self.definition.location, 'bin')
13611405
1362 def register_parser(self, subparsers):1406 def register_parser(self, subparsers):
1363 self.add_subcommand(subparsers)1407 """
1408 Overridden method of CommandBase.
1409
1410 :param subparsers:
1411 The argparse subparsers objects in which command line argument
1412 specification should be created.
1413
1414 This method is invoked by the command line handling code to register
1415 arguments specific to this sub-command. It must also register itself as
1416 the command class with the ``command`` default.
1417 """
1418 parser = self.add_subcommand(subparsers)
1419 group = parser.add_argument_group(title=_("test options"))
1420 group.add_argument(
1421 '-i', '--inline', action='store_true',
1422 help=_("Only job inline commands"))
1423 group.add_argument(
1424 '-f', '--flake8', action='store_true',
1425 help=_("Only Flake8"))
1426 group.add_argument(
1427 '-s', '--shellcheck', action='store_true',
1428 help=_("Only ShellCheck"))
1429 group.add_argument(
1430 '-u', '--unittest', action='store_true',
1431 help=_("Only unittest from tests/ dir"))
13641432
1365 def invoked(self, ns):1433 def invoked(self, ns):
1366 sys.path.insert(0, self.scripts_dir)1434 sys.path.insert(0, self.scripts_dir)
1367 runner = TextTestRunner(verbosity=2)1435 runner = TextTestRunner(verbosity=2)
1436 provider = self.get_provider()
13681437
1369 # create unittest for each bin/*.sh file1438 # create unittest for each bin/*.sh file
1370 for file in glob.glob(self.scripts_dir + "/*.sh"):1439 for file in glob.glob(self.scripts_dir + "/*.sh"):
1371 test_method = create_test(file)1440 test_method = create_shellcheck_test(file)
1372 test_method.__name__ = 'test_shellcheck_{}'.format(1441 test_method.__name__ = 'test_shellcheck_{}'.format(file)
1373 os.path.splitext(file)[0])
1374 setattr(ShellcheckTests, test_method.__name__, test_method)1442 setattr(ShellcheckTests, test_method.__name__, test_method)
1443
1375 shellcheck_suite = defaultTestLoader.loadTestsFromTestCase(1444 shellcheck_suite = defaultTestLoader.loadTestsFromTestCase(
1376 ShellcheckTests)1445 ShellcheckTests)
13771446
1378 # find tests defined in tests/1447 # create unittest for each bin/*.py file
1379 tests_dir_suite = defaultTestLoader.discover(self.tests_dir)1448 for file in glob.glob(self.scripts_dir + "/*.py"):
1449 test_method = create_flake8_test(file)
1450 test_method.__name__ = 'test_flake8_{}'.format(file)
1451 setattr(Flake8Tests, test_method.__name__, test_method)
1452
1453 flake8_suite = defaultTestLoader.loadTestsFromTestCase(
1454 Flake8Tests)
13801455
1381 result = runner.run(unittest.TestSuite(1456 # create unittest for each job unit command
1382 [shellcheck_suite, tests_dir_suite]))1457 unit_list = provider.unit_list
1458 for unit in unit_list:
1459 if unit.Meta.name == 'template':
1460 unit._fake_resources = True
1461 accessed_parameters = unit.get_accessed_parameters(
1462 force=True, template_engine=unit.template_engine)
1463 resource = Resource({
1464 key: key.upper()
1465 for key in set(
1466 itertools.chain(*accessed_parameters.values()))
1467 })
1468 command = unit.instantiate_one(resource).command
1469 if command:
1470 test_method = create_inline_shellcheck_test(command)
1471 test_method.__name__ = 'test_job_command_{}_{}'.format(
1472 unit.origin.relative_to(self.definition.location),
1473 unit.partial_id)
1474 setattr(
1475 InlineShellcheckTests,
1476 test_method.__name__, test_method)
1477 elif unit.Meta.name == 'job' and unit.command:
1478 test_method = create_inline_shellcheck_test(unit.command)
1479 test_method.__name__ = 'test_job_command_{}_{}'.format(
1480 unit.origin.relative_to(self.definition.location),
1481 unit.partial_id)
1482 setattr(
1483 InlineShellcheckTests,
1484 test_method.__name__, test_method)
1485
1486 inline_shellcheck_suite = defaultTestLoader.loadTestsFromTestCase(
1487 InlineShellcheckTests)
1488
1489 # find tests defined in tests/
1490 if os.path.exists(self.tests_dir):
1491 tests_dir_suite = defaultTestLoader.discover(self.tests_dir)
1492 else:
1493 tests_dir_suite = unittest.TestSuite()
1494
1495 if ns.inline:
1496 result = runner.run(unittest.TestSuite([inline_shellcheck_suite]))
1497 elif ns.flake8:
1498 result = runner.run(unittest.TestSuite([flake8_suite]))
1499 elif ns.unittest:
1500 result = runner.run(unittest.TestSuite([tests_dir_suite]))
1501 elif ns.shellcheck:
1502 result = runner.run(unittest.TestSuite([shellcheck_suite]))
1503 else:
1504 result = runner.run(unittest.TestSuite([
1505 inline_shellcheck_suite,
1506 shellcheck_suite,
1507 flake8_suite,
1508 tests_dir_suite
1509 ]))
1383 if not result.wasSuccessful():1510 if not result.wasSuccessful():
1384 return 11511 return 1
13851512

Subscribers

People subscribed via source and target branches