From 923786f0db6c999f5af54d246bb48c9f64499016 Mon Sep 17 00:00:00 2001 From: PhillypHenning Date: Fri, 17 Mar 2023 12:44:14 -0400 Subject: [PATCH 01/11] adding test_parser.py --- scripts/plugins/config/parser.py | 3 +- scripts/plugins/utilities.py | 5 +- scripts/tests/unit/test_parser.py | 242 ++++++++++++++++++++++++++++++ 3 files changed, 246 insertions(+), 4 deletions(-) create mode 100644 scripts/tests/unit/test_parser.py diff --git a/scripts/plugins/config/parser.py b/scripts/plugins/config/parser.py index efb9fbbe..6c807cc2 100644 --- a/scripts/plugins/config/parser.py +++ b/scripts/plugins/config/parser.py @@ -37,8 +37,7 @@ def get_config_list(config_file, schema_file): f"Configuration value: [{item.name}] is required. Please ensure you " "set this configuration value in the plugins `bitops.config.yaml`" ) - logger.debug(item) - sys.exit(1) + sys.exit(1) return cli_config_list, options_config_list diff --git a/scripts/plugins/utilities.py b/scripts/plugins/utilities.py index b9012c5b..914be11e 100644 --- a/scripts/plugins/utilities.py +++ b/scripts/plugins/utilities.py @@ -47,8 +47,9 @@ def add_value_to_env(export_env, value): def load_yaml(inc_yaml, required=True): """ - This function attempts to load a YAML file from a given location, - and exits if the file is not found. It returns the loaded YAML file if successful. + This function attempts to load a YAML file from a given location. + It raises a FileNotFoundError exception if the file is not found + and returns the loaded YAML file if successful. """ out_yaml = None try: diff --git a/scripts/tests/unit/test_parser.py b/scripts/tests/unit/test_parser.py new file mode 100644 index 00000000..4057edda --- /dev/null +++ b/scripts/tests/unit/test_parser.py @@ -0,0 +1,242 @@ +import unittest +import yaml +from ...plugins.config.parser import ( + convert_yaml_to_dict, + parse_yaml_keys_to_list, + generate_populated_schema_list, + generate_schema_keys, + populate_parsed_configurations, +) +from ...plugins.utilities import load_yaml +from ...plugins.config.schema import SchemaObject + + +class TestConvertYamlToDict(unittest.TestCase): + def test_convert_yaml_to_dict_with_null_values(self): + # Setup + inc_yaml = {"testKey1": "testValue1", "testKey2": None} + null_replacement = "nullReplacement" + + # Execute + result = convert_yaml_to_dict(inc_yaml, null_replacement) + + # Assert + self.assertEqual(result.testKey1, "testValue1") + self.assertEqual(result.testKey0, "nullReplacement") + + def test_convert_yaml_to_dict_without_null_values(self): + # Setup + inc_yaml = {"testKey1": "testValue1", "testKey2": None} + + # Execute + result = convert_yaml_to_dict(inc_yaml) + + # Assert + self.assertEqual(result.testKey1, "testValue1") + self.assertEqual(result.testKey2, None) + + # test_convert_yaml_to_dict_with_invalid_dict + # Function not needed. DefaultMunch handles incorrect typing + + +class TestParseYamlKeysToList(unittest.TestCase): + def setUp(self): + self.valid_schema = { + "terraform": { + "type": "object", + "properties": { + "cli": { + "type": "object", + "properties": { + "targets": { + "type": "list", + "parameter": "target", + "export_env": "TF_TARGETS", + }, + "stack-action": { + "type": "string", + "export_env": "TERRAFORM_COMMAND", + "required": True, + "default": "plan", + }, + }, + }, + "options": { + "type": "object", + "properties": { + "skip-deploy": { + "type": "boolean", + "parameter": "skip-deploy", + "export_env": "TERRAFORM_SKIP_DEPLOY", + } + }, + }, + }, + }, + } + self.root_key = "terraform" + + def test_parse_yaml_keys_to_list(self): + """ + Test parsing yaml keys to list + """ + expected_keys_list = [ + "terraform.type", + "terraform.properties", + "terraform.properties.cli", + "terraform.properties.cli.type", + "terraform.properties.cli.properties", + "terraform.properties.cli.properties.targets", + "terraform.properties.cli.properties.targets.type", + "terraform.properties.cli.properties.targets.parameter", + "terraform.properties.cli.properties.targets.export_env", + "terraform.properties.cli.properties.stack-action", + "terraform.properties.cli.properties.stack-action.type", + "terraform.properties.cli.properties.stack-action.export_env", + "terraform.properties.cli.properties.stack-action.required", + "terraform.properties.cli.properties.stack-action.default", + "terraform.properties.options", + "terraform.properties.options.type", + "terraform.properties.options.properties", + "terraform.properties.options.properties.skip-deploy", + "terraform.properties.options.properties.skip-deploy.type", + "terraform.properties.options.properties.skip-deploy.parameter", + "terraform.properties.options.properties.skip-deploy.export_env", + ] + actual_keys_list = parse_yaml_keys_to_list(self.valid_schema, self.root_key) + self.assertListEqual(expected_keys_list, actual_keys_list) + self.assertIsInstance(actual_keys_list, list) + + def test_parse_yaml_keys_to_list_invalid_rootkey(self): + """ + Test prase_yaml_kwys_to_list with invalid rootkey. + Expecting KeyError + """ + with self.assertRaises(KeyError): + parse_yaml_keys_to_list(self.valid_schema, "not_a_root_key") + + def test_parse_yaml_keys_to_list_invalid_schema(self): + """ + Test prase_yaml_kwys_to_list with invalid rootkey. + Expecting TypeError + """ + with self.assertRaises(TypeError): + parse_yaml_keys_to_list("not_a_schema", self.root_key) + + +class TestGeneratePopulatedSchemaList(unittest.TestCase): + def setUp(self): + self.valid_schema = { + "terraform": { + "type": "object", + "properties": { + "cli": { + "type": "object", + "properties": { + "targets": { + "type": "list", + "parameter": "target", + "export_env": "TF_TARGETS", + }, + "stack-action": { + "type": "string", + "export_env": "TERRAFORM_COMMAND", + "required": True, + "default": "plan", + }, + }, + }, + "options": { + "type": "object", + "properties": { + "skip-deploy": { + "type": "boolean", + "parameter": "skip-deploy", + "export_env": "TERRAFORM_SKIP_DEPLOY", + } + }, + }, + }, + }, + } + self.config_yaml = { + "terraform": {"cli": {"stack-action": "apply"}, "options": {"skip-deploy": True}}, + } + + def test_generate_populated_schema_list(self): + schema_properties_list = generate_schema_keys(self.valid_schema) + result = generate_populated_schema_list( + convert_yaml_to_dict(self.valid_schema), schema_properties_list, self.config_yaml + ) + + self.assertEqual(len(result), 3) + self.assertTrue(isinstance(result[0], SchemaObject)) + self.assertEqual(result[0].name, "targets") + self.assertEqual(result[1].name, "stack-action") + self.assertEqual(result[2].name, "skip-deploy") + self.assertEqual(result[0].plugin, "terraform") + self.assertEqual(result[0].export_env, "TF_TARGETS") + self.assertEqual(result[0].default, None) + self.assertEqual(result[1].default, "plan") + self.assertEqual(result[0].enabled, None) + self.assertEqual(result[0].type, "list") + self.assertEqual(result[1].parameter, None) + self.assertEqual(result[1].required, True) + self.assertEqual(result[1].dash_type, None) + self.assertEqual(result[0].description, None) + + +class TestGenerateSchemaKeys(unittest.TestCase): + def test_schema_keys_list_not_empty(self): + """Test that the generated schema keys list is not empty""" + schema = { + "example_schema": {"property_1": {"type": "string"}, "property_2": {"type": "integer"}} + } + self.assertFalse(not generate_schema_keys(schema)) + self.assertEqual(len(generate_schema_keys(schema)), 2) + + def test_schema_keys_list_contains_correct_values(self): + """Test that the generated schema keys list contains the correct values""" + schema = { + "example_schema": {"property_1": {"type": "string"}, "property_2": {"type": "integer"}} + } + self.assertIn("example_schema.property_1", generate_schema_keys(schema)) + self.assertIn("example_schema.property_2", generate_schema_keys(schema)) + + +# class TestPopulateParsedConfigurations(unittest.TestCase): +# def test_bad_config_list(self): +# schema_list = [ +# {"value": "BAD_CONFIG", "schema_property_type": "cli", "required": False}, +# {"value": "GOOD_CONFIG", "schema_property_type": "cli", "required": False}, +# {"value": "", "schema_property_type": "options", "required": True}, +# ] +# bad_config_list = populate_parsed_configurations(schema_list)[0] +# self.assertEqual(len(bad_config_list), 1) +# self.assertEqual(bad_config_list[0]["value"], "BAD_CONFIG") + +# def test_parsed_schema_list(self): +# schema_list = [ +# {"value": "BAD_CONFIG", "schema_property_type": "cli", "required": False}, +# {"value": "GOOD_CONFIG", "schema_property_type": "cli", "required": False}, +# {"value": "", "schema_property_type": "options", "required": True}, +# ] +# parsed_schema_list = populate_parsed_configurations(schema_list)[1] +# self.assertEqual(len(parsed_schema_list), 2) +# self.assertEqual(parsed_schema_list[0]["value"], "GOOD_CONFIG") +# self.assertEqual(parsed_schema_list[1]["value"], "") + +# def test_required_config_list(self): +# schema_list = [ +# {"value": "BAD_CONFIG", "schema_property_type": "cli", "required": False}, +# {"value": "GOOD_CONFIG", "schema_property_type": "cli", "required": False}, +# {"value": "", "schema_property_type": "options", "required": True}, +# ] +# required_config_list = populate_parsed_configurations(schema_list)[2] +# self.assertEqual(len(required_config_list), 1) +# self.assertEqual(required_config_list[0]["value"], "") +# self.assertEqual(required_config_list[0]["required"], True) + + +if __name__ == "__main__": + unittest.main() From dde23de02ce1d980230fbd319ad541d92b6dd663 Mon Sep 17 00:00:00 2001 From: PhillypHenning Date: Fri, 17 Mar 2023 15:58:36 -0400 Subject: [PATCH 02/11] Adding tests for all parser.py functions --- scripts/plugins/config/parser.py | 10 +- scripts/plugins/deploy_plugins.py | 7 +- scripts/tests/unit/assets/example.config.yaml | 5 + scripts/tests/unit/assets/example.schema.yaml | 18 ++ scripts/tests/unit/test_parser.py | 156 ++++++++++++++---- 5 files changed, 155 insertions(+), 41 deletions(-) create mode 100644 scripts/tests/unit/assets/example.config.yaml create mode 100644 scripts/tests/unit/assets/example.schema.yaml diff --git a/scripts/plugins/config/parser.py b/scripts/plugins/config/parser.py index 6c807cc2..be0dd13f 100644 --- a/scripts/plugins/config/parser.py +++ b/scripts/plugins/config/parser.py @@ -28,11 +28,11 @@ def get_config_list(config_file, schema_file): ( cli_config_list, options_config_list, - required_config_list, + missing_required_config_list, ) = populate_parsed_configurations(schema_list) - if required_config_list: + if missing_required_config_list: logger.warning("\n~~~~~ REQUIRED CONFIG ~~~~~") - for item in required_config_list: + for item in missing_required_config_list: logger.error( f"Configuration value: [{item.name}] is required. Please ensure you " "set this configuration value in the plugins `bitops.config.yaml`" @@ -126,7 +126,7 @@ def populate_parsed_configurations(schema_list): options_config_list = [ item for item in parsed_schema_list if item.schema_property_type == "options" ] - required_config_list = [ + missing_required_config_list = [ item for item in parsed_schema_list if item.required is True and not item.value ] @@ -139,4 +139,4 @@ def populate_parsed_configurations(schema_list): logger.debug("\n~~~~~ BAD SCHEMA CONFIG ~~~~~") for item in bad_config_list: logger.debug(item) - return (cli_config_list, options_config_list, required_config_list) + return (cli_config_list, options_config_list, missing_required_config_list) diff --git a/scripts/plugins/deploy_plugins.py b/scripts/plugins/deploy_plugins.py index 9597cf43..c53a6b77 100644 --- a/scripts/plugins/deploy_plugins.py +++ b/scripts/plugins/deploy_plugins.py @@ -218,8 +218,11 @@ def deploy_plugins(): # pylint: disable=too-many-locals,too-many-branches,too-m if plugin_deploy_schema_parsing_flag: logger.debug("running bitops schema parsing...") - cli_config_list, _ = get_config_list(opsrepo_config_file, plugin_schema_file) - + try: + cli_config_list, _ = get_config_list(opsrepo_config_file, plugin_schema_file) + except FileNotFoundError: + logger.error(f"Schema and Configuration files are required. Exiting...") + sys.exit(2) # Compose a CLI and export it as "BITOPS_{PLUGIN}_CLI}" cli = PluginConfigCLI(cli_config_list) os.environ[cli.env] = cli.command diff --git a/scripts/tests/unit/assets/example.config.yaml b/scripts/tests/unit/assets/example.config.yaml new file mode 100644 index 00000000..9832e5c3 --- /dev/null +++ b/scripts/tests/unit/assets/example.config.yaml @@ -0,0 +1,5 @@ +example: + cli: + example-file: this.example-file + options: + skip-example: true \ No newline at end of file diff --git a/scripts/tests/unit/assets/example.schema.yaml b/scripts/tests/unit/assets/example.schema.yaml new file mode 100644 index 00000000..9690a8c7 --- /dev/null +++ b/scripts/tests/unit/assets/example.schema.yaml @@ -0,0 +1,18 @@ +example: + type: object + properties: + cli: + type: object + properties: + example-file: + type: string + parameter: example-file + export_env: EXAMPLE_FILE + options: + type: object + properties: + skip-example: + type: boolean + parameter: skip-example + export_env: SKIP_EXAMPLE + \ No newline at end of file diff --git a/scripts/tests/unit/test_parser.py b/scripts/tests/unit/test_parser.py index 4057edda..d29558ea 100644 --- a/scripts/tests/unit/test_parser.py +++ b/scripts/tests/unit/test_parser.py @@ -1,14 +1,48 @@ import unittest -import yaml +import os + +from munch import DefaultMunch from ...plugins.config.parser import ( convert_yaml_to_dict, parse_yaml_keys_to_list, generate_populated_schema_list, generate_schema_keys, populate_parsed_configurations, + get_config_list, ) -from ...plugins.utilities import load_yaml from ...plugins.config.schema import SchemaObject +from ...plugins.logging import turn_off_logger + +turn_off_logger() + + +class TestGetConfigList(unittest.TestCase): + def setUp(self): + self.root_dir = os.getcwd() + + def test_get_config_list_valid_inputs(self): + config_file = "example.config.yaml" + schema_file = "example.schema.yaml" + cli_config_list, options_config_list = get_config_list( + f"{self.root_dir}/scripts/tests/test_assets/{config_file}", + f"{self.root_dir}/scripts/tests/test_assets/{schema_file}", + ) + self.assertIsNotNone(cli_config_list) + self.assertIsNotNone(options_config_list) + self.assertIsInstance(cli_config_list, list) + self.assertIsInstance(options_config_list, list) + + def test_get_config_list_invalid_file(self): + config_file = "invalid_config.yml" + schema_file = "invalid_schema.yml" + with self.assertRaises(FileNotFoundError): + get_config_list(config_file, schema_file) + + # def test_get_config_list_missing_required_config(self): + # config_file = "config.yml" + # schema_file = "schema.yml" + # with self.assertRaises(SystemExit): + # get_config_list(config_file, schema_file) class TestConvertYamlToDict(unittest.TestCase): @@ -204,38 +238,92 @@ def test_schema_keys_list_contains_correct_values(self): self.assertIn("example_schema.property_2", generate_schema_keys(schema)) -# class TestPopulateParsedConfigurations(unittest.TestCase): -# def test_bad_config_list(self): -# schema_list = [ -# {"value": "BAD_CONFIG", "schema_property_type": "cli", "required": False}, -# {"value": "GOOD_CONFIG", "schema_property_type": "cli", "required": False}, -# {"value": "", "schema_property_type": "options", "required": True}, -# ] -# bad_config_list = populate_parsed_configurations(schema_list)[0] -# self.assertEqual(len(bad_config_list), 1) -# self.assertEqual(bad_config_list[0]["value"], "BAD_CONFIG") - -# def test_parsed_schema_list(self): -# schema_list = [ -# {"value": "BAD_CONFIG", "schema_property_type": "cli", "required": False}, -# {"value": "GOOD_CONFIG", "schema_property_type": "cli", "required": False}, -# {"value": "", "schema_property_type": "options", "required": True}, -# ] -# parsed_schema_list = populate_parsed_configurations(schema_list)[1] -# self.assertEqual(len(parsed_schema_list), 2) -# self.assertEqual(parsed_schema_list[0]["value"], "GOOD_CONFIG") -# self.assertEqual(parsed_schema_list[1]["value"], "") - -# def test_required_config_list(self): -# schema_list = [ -# {"value": "BAD_CONFIG", "schema_property_type": "cli", "required": False}, -# {"value": "GOOD_CONFIG", "schema_property_type": "cli", "required": False}, -# {"value": "", "schema_property_type": "options", "required": True}, -# ] -# required_config_list = populate_parsed_configurations(schema_list)[2] -# self.assertEqual(len(required_config_list), 1) -# self.assertEqual(required_config_list[0]["value"], "") -# self.assertEqual(required_config_list[0]["required"], True) +class TestPopulateParsedConfigurations(unittest.TestCase): + def setUp(self): + self.valid_schema = { + "terraform": { + "type": "object", + "properties": { + "cli": { + "type": "object", + "properties": { + "targets": { + "type": "list", + "parameter": "target", + "export_env": "TF_TARGETS", + }, + "stack-action": { + "type": "string", + "export_env": "TERRAFORM_COMMAND", + "required": True, + "default": "plan", + }, + }, + }, + "options": { + "type": "object", + "properties": { + "skip-deploy": { + "type": "boolean", + "parameter": "skip-deploy", + "export_env": "TERRAFORM_SKIP_DEPLOY", + } + }, + }, + }, + }, + } + self.config_yaml = { + "terraform": {"cli": {"stack-action": "apply"}, "options": {"skip-deploy": True}}, + } + schema_properties_list = generate_schema_keys(self.valid_schema) + self.schema_list = generate_populated_schema_list( + convert_yaml_to_dict(self.valid_schema), schema_properties_list, self.config_yaml + ) + + def test_cli_config_list(self): + cli_config_list = populate_parsed_configurations(self.schema_list)[0] + # for item in cli_config_list: + # print(item) + self.assertEqual(cli_config_list[0].schema_property_type, "cli") + self.assertEqual(cli_config_list[1].schema_property_type, "cli") + with self.assertRaises(IndexError): + cli_config_list[2] + + def test_options_config_list(self): + options_config_list = populate_parsed_configurations(self.schema_list)[1] + + self.assertEqual(options_config_list[0].schema_property_type, "options") + with self.assertRaises(IndexError): + options_config_list[1] + + def test_missing_required_config_list_empty_list(self): + required_config_list = populate_parsed_configurations(self.schema_list)[2] + self.assertFalse(required_config_list) + + def test_missing_required_config_list(self): + test_required_schema_value = [ + SchemaObject( + "test_config", + "terraform.cli.test_config", + DefaultMunch.fromDict( + { + "type": "string", + "export_env": "TEST_COMMAND", + "required": True, + "default": "", + } + ), + ) + ] + + self.schema_list += test_required_schema_value + required_config_list = populate_parsed_configurations(self.schema_list)[2] + self.assertTrue(required_config_list) + self.assertEqual(required_config_list[0].name, "test_config") + self.assertTrue(required_config_list[0].required) + with self.assertRaises(IndexError): + required_config_list[1] if __name__ == "__main__": From 067a61cc5be12678edbe89ca15c33cb431d0de7b Mon Sep 17 00:00:00 2001 From: PhillypHenning Date: Fri, 17 Mar 2023 16:42:31 -0400 Subject: [PATCH 03/11] adding docstrings --- scripts/tests/unit/test_parser.py | 33 ++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/scripts/tests/unit/test_parser.py b/scripts/tests/unit/test_parser.py index d29558ea..b1051b7c 100644 --- a/scripts/tests/unit/test_parser.py +++ b/scripts/tests/unit/test_parser.py @@ -17,10 +17,13 @@ class TestGetConfigList(unittest.TestCase): + """Test parser.py get_config_list function""" + def setUp(self): self.root_dir = os.getcwd() def test_get_config_list_valid_inputs(self): + """Test parser.py get_config_list function with valid inputs""" config_file = "example.config.yaml" schema_file = "example.schema.yaml" cli_config_list, options_config_list = get_config_list( @@ -33,20 +36,18 @@ def test_get_config_list_valid_inputs(self): self.assertIsInstance(options_config_list, list) def test_get_config_list_invalid_file(self): + """Test parser.py get_config_list function with invalid inputs""" config_file = "invalid_config.yml" schema_file = "invalid_schema.yml" with self.assertRaises(FileNotFoundError): get_config_list(config_file, schema_file) - # def test_get_config_list_missing_required_config(self): - # config_file = "config.yml" - # schema_file = "schema.yml" - # with self.assertRaises(SystemExit): - # get_config_list(config_file, schema_file) - class TestConvertYamlToDict(unittest.TestCase): + """Test parser.py convert_yaml_to_dict function""" + def test_convert_yaml_to_dict_with_null_values(self): + """Test parser.py convert_yaml_to_dict function with null values replacement""" # Setup inc_yaml = {"testKey1": "testValue1", "testKey2": None} null_replacement = "nullReplacement" @@ -59,6 +60,7 @@ def test_convert_yaml_to_dict_with_null_values(self): self.assertEqual(result.testKey0, "nullReplacement") def test_convert_yaml_to_dict_without_null_values(self): + """Test parser.py convert_yaml_to_dict function without null values replacement""" # Setup inc_yaml = {"testKey1": "testValue1", "testKey2": None} @@ -69,11 +71,10 @@ def test_convert_yaml_to_dict_without_null_values(self): self.assertEqual(result.testKey1, "testValue1") self.assertEqual(result.testKey2, None) - # test_convert_yaml_to_dict_with_invalid_dict - # Function not needed. DefaultMunch handles incorrect typing - class TestParseYamlKeysToList(unittest.TestCase): + """Test parser.py parse_yaml_keys_to_list function""" + def setUp(self): self.valid_schema = { "terraform": { @@ -111,6 +112,7 @@ def setUp(self): self.root_key = "terraform" def test_parse_yaml_keys_to_list(self): + """Test parser.py parse_yaml_keys_to_list function""" """ Test parsing yaml keys to list """ @@ -142,6 +144,7 @@ def test_parse_yaml_keys_to_list(self): self.assertIsInstance(actual_keys_list, list) def test_parse_yaml_keys_to_list_invalid_rootkey(self): + """Test parser.py parse_yaml_keys_to_list function with invalid rootkey""" """ Test prase_yaml_kwys_to_list with invalid rootkey. Expecting KeyError @@ -150,6 +153,7 @@ def test_parse_yaml_keys_to_list_invalid_rootkey(self): parse_yaml_keys_to_list(self.valid_schema, "not_a_root_key") def test_parse_yaml_keys_to_list_invalid_schema(self): + """Test parser.py parse_yaml_keys_to_list function with invalid schema""" """ Test prase_yaml_kwys_to_list with invalid rootkey. Expecting TypeError @@ -159,6 +163,8 @@ def test_parse_yaml_keys_to_list_invalid_schema(self): class TestGeneratePopulatedSchemaList(unittest.TestCase): + """Test parser.py generate_populated_schema_list function""" + def setUp(self): self.valid_schema = { "terraform": { @@ -198,6 +204,7 @@ def setUp(self): } def test_generate_populated_schema_list(self): + """Test parser.py generate_populated_schema_list function""" schema_properties_list = generate_schema_keys(self.valid_schema) result = generate_populated_schema_list( convert_yaml_to_dict(self.valid_schema), schema_properties_list, self.config_yaml @@ -221,6 +228,8 @@ def test_generate_populated_schema_list(self): class TestGenerateSchemaKeys(unittest.TestCase): + """Test parser.py generate_schema_keys function""" + def test_schema_keys_list_not_empty(self): """Test that the generated schema keys list is not empty""" schema = { @@ -239,6 +248,8 @@ def test_schema_keys_list_contains_correct_values(self): class TestPopulateParsedConfigurations(unittest.TestCase): + """Test parser.py populate_parsed_configurations function""" + def setUp(self): self.valid_schema = { "terraform": { @@ -282,6 +293,7 @@ def setUp(self): ) def test_cli_config_list(self): + """Test parser.py populate_parsed_configurations function - return cli list""" cli_config_list = populate_parsed_configurations(self.schema_list)[0] # for item in cli_config_list: # print(item) @@ -291,6 +303,7 @@ def test_cli_config_list(self): cli_config_list[2] def test_options_config_list(self): + """Test parser.py populate_parsed_configurations function - return options list""" options_config_list = populate_parsed_configurations(self.schema_list)[1] self.assertEqual(options_config_list[0].schema_property_type, "options") @@ -298,10 +311,12 @@ def test_options_config_list(self): options_config_list[1] def test_missing_required_config_list_empty_list(self): + """Test parser.py populate_parsed_configurations function - doesn't return required list""" required_config_list = populate_parsed_configurations(self.schema_list)[2] self.assertFalse(required_config_list) def test_missing_required_config_list(self): + """Test parser.py populate_parsed_configurations function - return required list""" test_required_schema_value = [ SchemaObject( "test_config", From 6de76f8906249e88704297f1cf46d33d3d291999 Mon Sep 17 00:00:00 2001 From: PhillypHenning Date: Mon, 20 Mar 2023 12:04:31 -0400 Subject: [PATCH 04/11] Making bsformat happy --- scripts/plugins/config/parser.py | 5 +++- scripts/plugins/deploy_plugins.py | 2 +- scripts/tests/unit/test_parser.py | 43 ++++++++++++++----------------- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/scripts/plugins/config/parser.py b/scripts/plugins/config/parser.py index be0dd13f..dff8998c 100644 --- a/scripts/plugins/config/parser.py +++ b/scripts/plugins/config/parser.py @@ -1,4 +1,5 @@ import sys +import plugins.settings as settings # pylint: disable=consider-using-from-import from munch import DefaultMunch from ..logging import logger @@ -20,7 +21,9 @@ def get_config_list(config_file, schema_file): try: schema_yaml = load_yaml(schema_file) config_yaml = load_yaml(config_file) - except FileNotFoundError: + except FileNotFoundError as exc: + if settings.BITOPS_RUN_MODE == "testing": + raise exc sys.exit(2) schema = convert_yaml_to_dict(schema_yaml) schema_properties_list = generate_schema_keys(schema) diff --git a/scripts/plugins/deploy_plugins.py b/scripts/plugins/deploy_plugins.py index c53a6b77..f8a199fc 100644 --- a/scripts/plugins/deploy_plugins.py +++ b/scripts/plugins/deploy_plugins.py @@ -221,7 +221,7 @@ def deploy_plugins(): # pylint: disable=too-many-locals,too-many-branches,too-m try: cli_config_list, _ = get_config_list(opsrepo_config_file, plugin_schema_file) except FileNotFoundError: - logger.error(f"Schema and Configuration files are required. Exiting...") + logger.error("Schema and Configuration files are required. Exiting...") sys.exit(2) # Compose a CLI and export it as "BITOPS_{PLUGIN}_CLI}" cli = PluginConfigCLI(cli_config_list) diff --git a/scripts/tests/unit/test_parser.py b/scripts/tests/unit/test_parser.py index b1051b7c..3317d432 100644 --- a/scripts/tests/unit/test_parser.py +++ b/scripts/tests/unit/test_parser.py @@ -1,19 +1,25 @@ import unittest import os +import plugins.config.schema as Schema +import plugins.logging as Logging +import plugins.config.parser as Parser +import plugins.settings as settings # pylint: disable=consider-using-from-import + from munch import DefaultMunch -from ...plugins.config.parser import ( - convert_yaml_to_dict, - parse_yaml_keys_to_list, - generate_populated_schema_list, - generate_schema_keys, - populate_parsed_configurations, - get_config_list, -) -from ...plugins.config.schema import SchemaObject -from ...plugins.logging import turn_off_logger -turn_off_logger() + +settings.BITOPS_RUN_MODE = "testing" +SchemaObject = Schema.SchemaObject +Logging.turn_off_logger() + +# Flooding the namespace +convert_yaml_to_dict = Parser.convert_yaml_to_dict +parse_yaml_keys_to_list = Parser.parse_yaml_keys_to_list +generate_populated_schema_list = Parser.generate_populated_schema_list +generate_schema_keys = Parser.generate_schema_keys +populate_parsed_configurations = Parser.populate_parsed_configurations +get_config_list = Parser.get_config_list class TestGetConfigList(unittest.TestCase): @@ -27,8 +33,8 @@ def test_get_config_list_valid_inputs(self): config_file = "example.config.yaml" schema_file = "example.schema.yaml" cli_config_list, options_config_list = get_config_list( - f"{self.root_dir}/scripts/tests/test_assets/{config_file}", - f"{self.root_dir}/scripts/tests/test_assets/{schema_file}", + f"{self.root_dir}/scripts/tests/unit/assets/{config_file}", + f"{self.root_dir}/scripts/tests/unit/assets/{schema_file}", ) self.assertIsNotNone(cli_config_list) self.assertIsNotNone(options_config_list) @@ -112,7 +118,6 @@ def setUp(self): self.root_key = "terraform" def test_parse_yaml_keys_to_list(self): - """Test parser.py parse_yaml_keys_to_list function""" """ Test parsing yaml keys to list """ @@ -144,7 +149,6 @@ def test_parse_yaml_keys_to_list(self): self.assertIsInstance(actual_keys_list, list) def test_parse_yaml_keys_to_list_invalid_rootkey(self): - """Test parser.py parse_yaml_keys_to_list function with invalid rootkey""" """ Test prase_yaml_kwys_to_list with invalid rootkey. Expecting KeyError @@ -153,7 +157,6 @@ def test_parse_yaml_keys_to_list_invalid_rootkey(self): parse_yaml_keys_to_list(self.valid_schema, "not_a_root_key") def test_parse_yaml_keys_to_list_invalid_schema(self): - """Test parser.py parse_yaml_keys_to_list function with invalid schema""" """ Test prase_yaml_kwys_to_list with invalid rootkey. Expecting TypeError @@ -295,20 +298,14 @@ def setUp(self): def test_cli_config_list(self): """Test parser.py populate_parsed_configurations function - return cli list""" cli_config_list = populate_parsed_configurations(self.schema_list)[0] - # for item in cli_config_list: - # print(item) self.assertEqual(cli_config_list[0].schema_property_type, "cli") self.assertEqual(cli_config_list[1].schema_property_type, "cli") - with self.assertRaises(IndexError): - cli_config_list[2] def test_options_config_list(self): """Test parser.py populate_parsed_configurations function - return options list""" options_config_list = populate_parsed_configurations(self.schema_list)[1] self.assertEqual(options_config_list[0].schema_property_type, "options") - with self.assertRaises(IndexError): - options_config_list[1] def test_missing_required_config_list_empty_list(self): """Test parser.py populate_parsed_configurations function - doesn't return required list""" @@ -337,8 +334,6 @@ def test_missing_required_config_list(self): self.assertTrue(required_config_list) self.assertEqual(required_config_list[0].name, "test_config") self.assertTrue(required_config_list[0].required) - with self.assertRaises(IndexError): - required_config_list[1] if __name__ == "__main__": From d42ae8aaf8f5a2b58ff6661bacc5aa2787a0654a Mon Sep 17 00:00:00 2001 From: PhillypHenning Date: Fri, 17 Mar 2023 16:26:04 -0400 Subject: [PATCH 05/11] Adding SchemaObject unit tests --- scripts/plugins/config/schema.py | 9 +++- scripts/tests/unit/test_schema.py | 88 +++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 scripts/tests/unit/test_schema.py diff --git a/scripts/plugins/config/schema.py b/scripts/plugins/config/schema.py index ab07c9ad..58870056 100644 --- a/scripts/plugins/config/schema.py +++ b/scripts/plugins/config/schema.py @@ -165,7 +165,14 @@ def _apply_data_type(data_type, convert_value): if BITOPS_FAST_FAIL_MODE: logger.error(f"Data type not supported: [{data_type}]") - sys.exit(101) + raise UnSupportDataType(f"Data type not supported: [{data_type}]") logger.warning(f"Data type not supported: [{data_type}]") return None + + +class UnSupportDataType(Exception): + """Raised when an unsupported data type is passed in to a function""" + + def __init__(self, message): + self.message = message diff --git a/scripts/tests/unit/test_schema.py b/scripts/tests/unit/test_schema.py new file mode 100644 index 00000000..626891e8 --- /dev/null +++ b/scripts/tests/unit/test_schema.py @@ -0,0 +1,88 @@ +import unittest +import os + +from ...plugins.config.schema import SchemaObject, UnSupportDataType + +from ...plugins.logging import turn_off_logger + +turn_off_logger() + + +class TestSchemaObject(unittest.TestCase): + def setUp(self): + self.name = "test_name" + self.schema_key = "test.cli.example_string_object" + self.schema_property_values = { + "export_env": "TEST_ENV", + "default": "NO DEFAULT FOUND", + "enabled": False, + "type": "string", + "parameter": "test_name", + "dash_type": "", + "required": True, + "description": None, + } + self.test_obj = SchemaObject(self.name, self.schema_key, self.schema_property_values) + + def test_init_set_properties(self): + self.assertEqual(self.test_obj.name, self.name) + self.assertEqual(self.test_obj.plugin, "test") + self.assertEqual(self.test_obj.schema_key, self.schema_key) + self.assertEqual(self.test_obj.config_key, "test.cli.example_string_object") + self.assertEqual(self.test_obj.value, "") + self.assertEqual(self.test_obj.schema_property_type, "cli") + self.assertEqual(self.test_obj.export_env, "TEST_ENV") + self.assertEqual(self.test_obj.default, "NO DEFAULT FOUND") + self.assertFalse(self.test_obj.enabled) + self.assertEqual(self.test_obj.type, "string") + self.assertEqual(self.test_obj.parameter, "test_name") + self.assertEqual(self.test_obj.dash_type, "") + self.assertTrue(self.test_obj.required) + + def test_env(self): + self.assertEqual(self.test_obj.env, "BITOPS_TEST_TEST_NAME") + + def test_process_config(self): + # test default + self.test_obj.process_config({}) + self.assertEqual(self.test_obj.value, self.test_obj.default) + + # test value from config + self.test_obj.process_config({"test": {"cli": {"example_string_object": "config_value"}}}) + self.assertEqual(self.test_obj.value, "config_value") + + # test value from env + os.environ["BITOPS_TEST_TEST_NAME"] = "env_value" + self.test_obj.process_config({}) + self.assertEqual(self.test_obj.value, "env_value") + + def test_get_nested_item(self): + search_dict = {"test": {"properties": "value"}} + key = "test.properties" + result = SchemaObject.get_nested_item(search_dict, key) + self.assertEqual(result, "value") + + def test_apply_data_type(self): + # test string + result = SchemaObject._apply_data_type("string", "value") + self.assertEqual(result, "value") + + # test int + result = SchemaObject._apply_data_type("int", "3") + self.assertEqual(result, 3) + + # test boolean + result = SchemaObject._apply_data_type("boolean", "true") + self.assertTrue(result) + + # test list + result = SchemaObject._apply_data_type("list", ["a", "b", "c"]) + self.assertEqual(result, ["a", "b", "c"]) + + # test invalid + with self.assertRaises(UnSupportDataType): + SchemaObject._apply_data_type("invalid", "value") + + +if __name__ == "__main__": + unittest.main() From 141e5d459d9b8c60e3d3b925c358ea074fa347cb Mon Sep 17 00:00:00 2001 From: PhillypHenning Date: Fri, 17 Mar 2023 16:38:03 -0400 Subject: [PATCH 06/11] Adding docstrings --- scripts/tests/unit/test_schema.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/tests/unit/test_schema.py b/scripts/tests/unit/test_schema.py index 626891e8..3e454953 100644 --- a/scripts/tests/unit/test_schema.py +++ b/scripts/tests/unit/test_schema.py @@ -9,6 +9,8 @@ class TestSchemaObject(unittest.TestCase): + """Testing the SchemaObject""" + def setUp(self): self.name = "test_name" self.schema_key = "test.cli.example_string_object" @@ -25,6 +27,7 @@ def setUp(self): self.test_obj = SchemaObject(self.name, self.schema_key, self.schema_property_values) def test_init_set_properties(self): + """Test SchemaObject __init__ function""" self.assertEqual(self.test_obj.name, self.name) self.assertEqual(self.test_obj.plugin, "test") self.assertEqual(self.test_obj.schema_key, self.schema_key) @@ -40,9 +43,11 @@ def test_init_set_properties(self): self.assertTrue(self.test_obj.required) def test_env(self): + """Test SchemaObject self.env value setter""" self.assertEqual(self.test_obj.env, "BITOPS_TEST_TEST_NAME") def test_process_config(self): + """Test SchemaObject process_config function""" # test default self.test_obj.process_config({}) self.assertEqual(self.test_obj.value, self.test_obj.default) @@ -57,12 +62,14 @@ def test_process_config(self): self.assertEqual(self.test_obj.value, "env_value") def test_get_nested_item(self): + """Test SchemaObject get_nested_item function""" search_dict = {"test": {"properties": "value"}} key = "test.properties" result = SchemaObject.get_nested_item(search_dict, key) self.assertEqual(result, "value") def test_apply_data_type(self): + """Test SchemaObject apply_data_type function""" # test string result = SchemaObject._apply_data_type("string", "value") self.assertEqual(result, "value") From 329b6f0e2b0bb1c13619fb2aa9d42b3094adc006 Mon Sep 17 00:00:00 2001 From: PhillypHenning Date: Mon, 20 Mar 2023 12:14:56 -0400 Subject: [PATCH 07/11] making pylint happy --- scripts/tests/unit/test_schema.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/scripts/tests/unit/test_schema.py b/scripts/tests/unit/test_schema.py index 3e454953..311cb4f1 100644 --- a/scripts/tests/unit/test_schema.py +++ b/scripts/tests/unit/test_schema.py @@ -1,9 +1,9 @@ import unittest import os -from ...plugins.config.schema import SchemaObject, UnSupportDataType +from plugins.config.schema import SchemaObject, UnSupportDataType -from ...plugins.logging import turn_off_logger +from plugins.logging import turn_off_logger turn_off_logger() @@ -71,24 +71,30 @@ def test_get_nested_item(self): def test_apply_data_type(self): """Test SchemaObject apply_data_type function""" # test string - result = SchemaObject._apply_data_type("string", "value") + result = SchemaObject._apply_data_type( # pylint: disable=protected-access + "string", "value" + ) self.assertEqual(result, "value") # test int - result = SchemaObject._apply_data_type("int", "3") + result = SchemaObject._apply_data_type("int", "3") # pylint: disable=protected-access self.assertEqual(result, 3) # test boolean - result = SchemaObject._apply_data_type("boolean", "true") + result = SchemaObject._apply_data_type( # pylint: disable=protected-access + "boolean", "true" + ) self.assertTrue(result) # test list - result = SchemaObject._apply_data_type("list", ["a", "b", "c"]) + result = SchemaObject._apply_data_type( # pylint: disable=protected-access + "list", ["a", "b", "c"] + ) self.assertEqual(result, ["a", "b", "c"]) # test invalid with self.assertRaises(UnSupportDataType): - SchemaObject._apply_data_type("invalid", "value") + SchemaObject._apply_data_type("invalid", "value") # pylint: disable=protected-access if __name__ == "__main__": From 0592985fcc9fa2d0208fea126f0a0710a397b6ac Mon Sep 17 00:00:00 2001 From: PhillypHenning Date: Mon, 20 Mar 2023 12:18:05 -0400 Subject: [PATCH 08/11] Adding `BITOPS_ENV_logging_output_dir` to settings --- scripts/plugins/settings.py | 2 ++ tox.ini | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/plugins/settings.py b/scripts/plugins/settings.py index 86222f32..6b965657 100644 --- a/scripts/plugins/settings.py +++ b/scripts/plugins/settings.py @@ -87,6 +87,7 @@ def parse_config(dictionary, dotted_key_list): BITOPS_ENV_run_mode = os.environ.get("BITOPS_MODE") # TODO: CLEAN BITOPS_ENV_logging_level = os.environ.get("BITOPS_LOGGING_LEVEL") BITOPS_ENV_plugin_dir = os.environ.get("BITOPS_PLUGIN_DIR") +BITOPS_ENV_logging_output_dir = os.environ.get("BITOPS_LOGGING_OUTPUT_DIR") BITOPS_ENV_default_folder = os.environ.get("BITOPS_DEFAULT_FOLDER") # v2.0.0: Fallback to 'ENVIRONMENT' in case when 'BITOPS_ENVIRONMENT' is not set @@ -141,6 +142,7 @@ def parse_config(dictionary, dotted_key_list): ) BITOPS_LOGGING_PATH = get_first( + BITOPS_ENV_logging_output_dir, parse_config(bitops_user_configuration, "bitops.logging.path"), parse_config(bitops_build_configuration, "bitops.logging.path"), "/var/log/bitops", diff --git a/tox.ini b/tox.ini index 46bbe72b..a5a2ee27 100644 --- a/tox.ini +++ b/tox.ini @@ -39,6 +39,6 @@ commands = # Run: # tox -e unit [testenv:unit] -setenv=BITOPS_LOGGING_PATH=./logs +setenv=BITOPS_LOGGING_OUTPUT_DIR=./logs commands = python3 -m unittest discover --verbose --top-level-directory scripts --start-directory scripts/ --pattern "test_*.py" From 3d2fdb9312bedc2dc124c956013f408236e52598 Mon Sep 17 00:00:00 2001 From: Eugen Date: Wed, 5 Apr 2023 19:21:56 +0100 Subject: [PATCH 09/11] Minor cosmetic renames --- scripts/plugins/config/parser.py | 9 ++++----- scripts/plugins/config/schema.py | 10 +++++----- scripts/plugins/settings.py | 4 ++-- scripts/tests/unit/test_parser.py | 31 +++++++++---------------------- scripts/tests/unit/test_schema.py | 8 ++------ 5 files changed, 22 insertions(+), 40 deletions(-) diff --git a/scripts/plugins/config/parser.py b/scripts/plugins/config/parser.py index 0aaec501..756cae91 100644 --- a/scripts/plugins/config/parser.py +++ b/scripts/plugins/config/parser.py @@ -1,10 +1,9 @@ import sys -import plugins.settings as settings # pylint: disable=consider-using-from-import from munch import DefaultMunch -from ..logging import logger -from ..utilities import load_yaml -from .schema import SchemaObject +from plugins.logging import logger +from plugins.utilities import load_yaml +from plugins.config.schema import SchemaObject def get_config_list(config_file, schema_file): @@ -26,7 +25,7 @@ def get_config_list(config_file, schema_file): f"Required config file was not found. \ To fix this please add the following file: [{e.filename}]" ) - sys.exit(101) + raise e schema = convert_yaml_to_dict(schema_yaml) schema_properties_list = generate_schema_keys(schema) schema_list = generate_populated_schema_list(schema, schema_properties_list, config_yaml) diff --git a/scripts/plugins/config/schema.py b/scripts/plugins/config/schema.py index 58870056..157937ff 100644 --- a/scripts/plugins/config/schema.py +++ b/scripts/plugins/config/schema.py @@ -2,9 +2,9 @@ import os import re -from ..logging import logger -from ..settings import BITOPS_FAST_FAIL_MODE -from ..utilities import add_value_to_env +from plugins.logging import logger +from plugins.settings import BITOPS_FAST_FAIL_MODE +from plugins.utilities import add_value_to_env class SchemaObject: # pylint: disable=too-many-instance-attributes @@ -165,13 +165,13 @@ def _apply_data_type(data_type, convert_value): if BITOPS_FAST_FAIL_MODE: logger.error(f"Data type not supported: [{data_type}]") - raise UnSupportDataType(f"Data type not supported: [{data_type}]") + raise SchemaUnsupportedDataType(f"Data type not supported: [{data_type}]") logger.warning(f"Data type not supported: [{data_type}]") return None -class UnSupportDataType(Exception): +class SchemaUnsupportedDataType(Exception): """Raised when an unsupported data type is passed in to a function""" def __init__(self, message): diff --git a/scripts/plugins/settings.py b/scripts/plugins/settings.py index 44f3a092..16c18a34 100644 --- a/scripts/plugins/settings.py +++ b/scripts/plugins/settings.py @@ -88,7 +88,7 @@ def parse_config(dictionary, dotted_key_list): BITOPS_ENV_logging_level = os.environ.get("BITOPS_LOGGING_LEVEL") BITOPS_ENV_logging_filename = os.environ.get("BITOPS_LOGGING_FILENAME") BITOPS_ENV_plugin_dir = os.environ.get("BITOPS_PLUGIN_DIR") -BITOPS_ENV_logging_output_dir = os.environ.get("BITOPS_LOGGING_OUTPUT_DIR") +BITOPS_ENV_logging_path = os.environ.get("BITOPS_LOGGING_PATH") BITOPS_ENV_default_folder = os.environ.get("BITOPS_DEFAULT_FOLDER") # v2.0.0: Fallback to 'ENVIRONMENT' in case when 'BITOPS_ENVIRONMENT' is not set @@ -144,7 +144,7 @@ def parse_config(dictionary, dotted_key_list): ) BITOPS_LOGGING_PATH = get_first( - BITOPS_ENV_logging_output_dir, + BITOPS_ENV_logging_path, parse_config(bitops_user_configuration, "bitops.logging.path"), parse_config(bitops_build_configuration, "bitops.logging.path"), "/var/log/bitops", diff --git a/scripts/tests/unit/test_parser.py b/scripts/tests/unit/test_parser.py index 3317d432..80605a89 100644 --- a/scripts/tests/unit/test_parser.py +++ b/scripts/tests/unit/test_parser.py @@ -1,27 +1,18 @@ import unittest import os -import plugins.config.schema as Schema -import plugins.logging as Logging -import plugins.config.parser as Parser -import plugins.settings as settings # pylint: disable=consider-using-from-import - +from plugins.config.schema import SchemaObject +from plugins.config.parser import ( + convert_yaml_to_dict, + parse_yaml_keys_to_list, + generate_populated_schema_list, + generate_schema_keys, + populate_parsed_configurations, + get_config_list, +) from munch import DefaultMunch -settings.BITOPS_RUN_MODE = "testing" -SchemaObject = Schema.SchemaObject -Logging.turn_off_logger() - -# Flooding the namespace -convert_yaml_to_dict = Parser.convert_yaml_to_dict -parse_yaml_keys_to_list = Parser.parse_yaml_keys_to_list -generate_populated_schema_list = Parser.generate_populated_schema_list -generate_schema_keys = Parser.generate_schema_keys -populate_parsed_configurations = Parser.populate_parsed_configurations -get_config_list = Parser.get_config_list - - class TestGetConfigList(unittest.TestCase): """Test parser.py get_config_list function""" @@ -334,7 +325,3 @@ def test_missing_required_config_list(self): self.assertTrue(required_config_list) self.assertEqual(required_config_list[0].name, "test_config") self.assertTrue(required_config_list[0].required) - - -if __name__ == "__main__": - unittest.main() diff --git a/scripts/tests/unit/test_schema.py b/scripts/tests/unit/test_schema.py index 311cb4f1..8aa32217 100644 --- a/scripts/tests/unit/test_schema.py +++ b/scripts/tests/unit/test_schema.py @@ -1,7 +1,7 @@ import unittest import os -from plugins.config.schema import SchemaObject, UnSupportDataType +from plugins.config.schema import SchemaObject, SchemaUnsupportedDataType from plugins.logging import turn_off_logger @@ -93,9 +93,5 @@ def test_apply_data_type(self): self.assertEqual(result, ["a", "b", "c"]) # test invalid - with self.assertRaises(UnSupportDataType): + with self.assertRaises(SchemaUnsupportedDataType): SchemaObject._apply_data_type("invalid", "value") # pylint: disable=protected-access - - -if __name__ == "__main__": - unittest.main() From a0499b13c170b93ec0fb364fcc571dee38d7285c Mon Sep 17 00:00:00 2001 From: Eugen Date: Wed, 5 Apr 2023 19:25:27 +0100 Subject: [PATCH 10/11] Fix newline at the end of files --- scripts/tests/unit/assets/bitops.before-deploy.d/before_test.sh | 1 - scripts/tests/unit/assets/example.config.yaml | 2 +- scripts/tests/unit/assets/example.schema.yaml | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/tests/unit/assets/bitops.before-deploy.d/before_test.sh b/scripts/tests/unit/assets/bitops.before-deploy.d/before_test.sh index 00d28c89..afa6bddf 100644 --- a/scripts/tests/unit/assets/bitops.before-deploy.d/before_test.sh +++ b/scripts/tests/unit/assets/bitops.before-deploy.d/before_test.sh @@ -3,4 +3,3 @@ echo "In before_test.sh" ls ../../ - diff --git a/scripts/tests/unit/assets/example.config.yaml b/scripts/tests/unit/assets/example.config.yaml index 9832e5c3..d1af8468 100644 --- a/scripts/tests/unit/assets/example.config.yaml +++ b/scripts/tests/unit/assets/example.config.yaml @@ -2,4 +2,4 @@ example: cli: example-file: this.example-file options: - skip-example: true \ No newline at end of file + skip-example: true diff --git a/scripts/tests/unit/assets/example.schema.yaml b/scripts/tests/unit/assets/example.schema.yaml index 9690a8c7..771755b6 100644 --- a/scripts/tests/unit/assets/example.schema.yaml +++ b/scripts/tests/unit/assets/example.schema.yaml @@ -15,4 +15,3 @@ example: type: boolean parameter: skip-example export_env: SKIP_EXAMPLE - \ No newline at end of file From 3edd1b19acc436dcfe7a75a6ece040ac7c965daa Mon Sep 17 00:00:00 2001 From: Eugen Date: Wed, 5 Apr 2023 20:47:34 +0100 Subject: [PATCH 11/11] Catch logging in the unit tests, so they're not printed to the test output --- scripts/tests/unit/test_parser.py | 23 ++++++++++++++--------- scripts/tests/unit/test_schema.py | 19 +++++++++++-------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/scripts/tests/unit/test_parser.py b/scripts/tests/unit/test_parser.py index 80605a89..4bb0ea27 100644 --- a/scripts/tests/unit/test_parser.py +++ b/scripts/tests/unit/test_parser.py @@ -1,5 +1,5 @@ -import unittest import os +from unittest import TestCase from plugins.config.schema import SchemaObject from plugins.config.parser import ( @@ -13,7 +13,7 @@ from munch import DefaultMunch -class TestGetConfigList(unittest.TestCase): +class TestGetConfigList(TestCase): """Test parser.py get_config_list function""" def setUp(self): @@ -36,11 +36,16 @@ def test_get_config_list_invalid_file(self): """Test parser.py get_config_list function with invalid inputs""" config_file = "invalid_config.yml" schema_file = "invalid_schema.yml" - with self.assertRaises(FileNotFoundError): - get_config_list(config_file, schema_file) + with self.assertLogs("bitops-logger", level="ERROR") as log: + with self.assertRaises(FileNotFoundError): + get_config_list(config_file, schema_file) + self.assertIn("Required config file was not found", log.output[0]) + self.assertIn( + "To fix this please add the following file: [invalid_schema.yml]", log.output[0] + ) -class TestConvertYamlToDict(unittest.TestCase): +class TestConvertYamlToDict(TestCase): """Test parser.py convert_yaml_to_dict function""" def test_convert_yaml_to_dict_with_null_values(self): @@ -69,7 +74,7 @@ def test_convert_yaml_to_dict_without_null_values(self): self.assertEqual(result.testKey2, None) -class TestParseYamlKeysToList(unittest.TestCase): +class TestParseYamlKeysToList(TestCase): """Test parser.py parse_yaml_keys_to_list function""" def setUp(self): @@ -156,7 +161,7 @@ def test_parse_yaml_keys_to_list_invalid_schema(self): parse_yaml_keys_to_list("not_a_schema", self.root_key) -class TestGeneratePopulatedSchemaList(unittest.TestCase): +class TestGeneratePopulatedSchemaList(TestCase): """Test parser.py generate_populated_schema_list function""" def setUp(self): @@ -221,7 +226,7 @@ def test_generate_populated_schema_list(self): self.assertEqual(result[0].description, None) -class TestGenerateSchemaKeys(unittest.TestCase): +class TestGenerateSchemaKeys(TestCase): """Test parser.py generate_schema_keys function""" def test_schema_keys_list_not_empty(self): @@ -241,7 +246,7 @@ def test_schema_keys_list_contains_correct_values(self): self.assertIn("example_schema.property_2", generate_schema_keys(schema)) -class TestPopulateParsedConfigurations(unittest.TestCase): +class TestPopulateParsedConfigurations(TestCase): """Test parser.py populate_parsed_configurations function""" def setUp(self): diff --git a/scripts/tests/unit/test_schema.py b/scripts/tests/unit/test_schema.py index 8aa32217..625c7fdf 100644 --- a/scripts/tests/unit/test_schema.py +++ b/scripts/tests/unit/test_schema.py @@ -1,14 +1,10 @@ -import unittest import os +from unittest import TestCase from plugins.config.schema import SchemaObject, SchemaUnsupportedDataType -from plugins.logging import turn_off_logger -turn_off_logger() - - -class TestSchemaObject(unittest.TestCase): +class TestSchemaObject(TestCase): """Testing the SchemaObject""" def setUp(self): @@ -92,6 +88,13 @@ def test_apply_data_type(self): ) self.assertEqual(result, ["a", "b", "c"]) + def test_apply_data_type_invalid(self): + """Test SchemaObject apply_data_type function with invalid data + type should throw an Exception and print an error to stdout""" # test invalid - with self.assertRaises(SchemaUnsupportedDataType): - SchemaObject._apply_data_type("invalid", "value") # pylint: disable=protected-access + with self.assertLogs("bitops-logger", level="ERROR") as captured: + with self.assertRaises(SchemaUnsupportedDataType): + SchemaObject._apply_data_type( # pylint: disable=protected-access + "invalid", "value" + ) + self.assertIn("Data type not supported: [invalid]", captured.output[0])