From 5ec25754b1a7e6208ca71411534d41b407df6fd7 Mon Sep 17 00:00:00 2001 From: Shankar M S Date: Tue, 26 Nov 2019 10:08:04 +0100 Subject: [PATCH 01/13] [WIP] k-82: refactor, test_tf_service added --- Pipfile.lock | 26 +- cli/kaos_cli/services/terraform_service.py | 3 +- .../services/tests/test_tf_service.py | 240 ++++++++++++++++++ cli/kaos_cli/utils/tests/test_validation.py | 2 + cli/requirements.txt | 4 +- 5 files changed, 260 insertions(+), 15 deletions(-) create mode 100644 cli/kaos_cli/services/tests/test_tf_service.py diff --git a/Pipfile.lock b/Pipfile.lock index 519481c..3614333 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -107,6 +107,13 @@ ], "version": "==0.4.3" }, + "parameterized": { + "hashes": [ + "sha256:6a94dbea30c6abde99fd4c2f2042c1bf7f980e48908bf92ead62394f93cf57ed", + "sha256:ea0326ba5bbbe7c427329a27b75003410df07d1173ca254976f8f5a64922c322" + ], + "version": "==0.7.1" + }, "ptable": { "hashes": [ "sha256:aa7fc151cb40f2dabcd2275ba6f7fd0ff8577a86be3365cd3fb297cbe09cc292" @@ -186,13 +193,6 @@ } }, "develop": { - "atomicwrites": { - "hashes": [ - "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", - "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" - ], - "version": "==1.3.0" - }, "attrs": { "hashes": [ "sha256:08a96c641c3a74e44eb59afb61a24f2cb9f4d7188748e76ba4bb5edfa3cb7d1c", @@ -470,10 +470,10 @@ }, "pluggy": { "hashes": [ - "sha256:0db4b7601aae1d35b4a033282da476845aa19185c1e6964b25cf324b5e4ec3e6", - "sha256:fa5fa1622fa6dd5c030e9cad086fa19ef6a0cf6d7a2d12318e10cb49d6d68f34" + "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", + "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" ], - "version": "==0.13.0" + "version": "==0.13.1" }, "protobuf": { "hashes": [ @@ -536,10 +536,10 @@ }, "pytest": { "hashes": [ - "sha256:8e256fe71eb74e14a4d20a5987bb5e1488f0511ee800680aaedc62b9358714e8", - "sha256:ff0090819f669aaa0284d0f4aad1a6d9d67a6efdc6dd4eb4ac56b704f890a0d6" + "sha256:1897d74f60a5d8be02e06d708b41bf2445da2ee777066bd68edf14474fc201eb", + "sha256:f6a567e20c04259d41adce9a360bd8991e6aa29dd9695c5e6bd25a9779272673" ], - "version": "==5.2.4" + "version": "==5.3.0" }, "pytest-mock": { "hashes": [ diff --git a/cli/kaos_cli/services/terraform_service.py b/cli/kaos_cli/services/terraform_service.py index 45adba5..2cf26a0 100644 --- a/cli/kaos_cli/services/terraform_service.py +++ b/cli/kaos_cli/services/terraform_service.py @@ -13,8 +13,9 @@ def append(self, cmd): self.history.append(cmd) def execute(self): - self.run_cmd(";".join(self.history)) + exitcode, out, err = self.run_cmd(";".join(self.history)) self.clear() + return exitcode, out, err def clear(self): self.history = [] diff --git a/cli/kaos_cli/services/tests/test_tf_service.py b/cli/kaos_cli/services/tests/test_tf_service.py new file mode 100644 index 0000000..64bc238 --- /dev/null +++ b/cli/kaos_cli/services/tests/test_tf_service.py @@ -0,0 +1,240 @@ +import os +import pytest +from parameterized import parameterized +import logging +import subprocess + +from unittest import TestCase, mock + +from kaos_cli.services.terraform_service import TerraformService +from kaos_cli.services.tests import create_terraform_service +from kaos_cli.services.terraform_service import Command +from kaos_cli.utils.helpers import verbose_run, run_cmd +from kaos_cli.constants import KAOS_STATE_DIR + + +def command_append_data(): + return [ + ( + [], + ), + ( + ['echo <---first_echo_command--->'], + ), + ( + ['echo <---first_echo_command--->', 'echo <--- executing the second echo command --->'], + ), + ( + ['echo <--- executing the first echo command --->', 'echo <--- executing the second echo command --->', + 'echo <--- executing the third echo command --->'], + ), + ] + + +def command_execute_data(): + return [ + ( + ['echo <---first_echo_command--->', 'echo <--- executing the second echo command --->'], + ), + ( + ['echo <--- executing the first echo command --->', 'echo <--- executing the second echo command --->', + 'echo <--- executing the third echo command --->'], + ), + ] + + +class TestTerraformService(TestCase): + + @parameterized.expand(command_append_data) + def test_command_append(self, command_append_data): + + # Arrange + command = Command() + + # Act + for cmd in command_append_data: + command.append(cmd) + + # Assert + self.assertEqual(command.history, command_append_data) + + @parameterized.expand(command_execute_data) + def test_command_execute(self, command_execute_data): + + # Arrange + command = Command() + + # Act + for cmd in command_execute_data: + command.append(cmd) + + exitcode, out, err = command.execute() + + # Assert + self.assertEqual(exitcode, 0) + + @parameterized.expand(command_append_data) + def test_command_clear(self, command_append_data): + + # Arrange + command = Command() + + # Act + for cmd in command_append_data: + command.append(cmd) + + command.clear() + + # Assert + self.assertEqual(command.history, []) + + @parameterized.expand(command_execute_data) + def test_command_verbose_true(self, command_execute_data): + + # Arrange + command = Command() + verbose = True + + # Act + for cmd in command_execute_data: + command.set_verbose(verbose) + + # Assert + self.assertIsInstance(command.run_cmd, type(command.run_cmd)) + self.assertEqual(command.run_cmd.func, verbose_run) + self.assertEqual(command.run_cmd.args[0], True) + + @parameterized.expand(command_execute_data) + def test_command_verbose_false(self, command_execute_data): + + # Arrange + command = Command() + verbose = False + + # Act + for cmd in command_execute_data: + command.set_verbose(verbose) + + # Assert + self.assertIsInstance(command.run_cmd, type(command.run_cmd)) + self.assertEqual(command.run_cmd.func, verbose_run) + self.assertEqual(command.run_cmd.args[0], False) + + @parameterized.expand(command_execute_data) + def test_tf_service_set_verbose_True(self, command_execute_data): + + # Arrange + verbose = True + command = Command() + + # Act + for cmd in command_execute_data: + command.append(cmd) + + tf_service = TerraformService(cmd=command) + tf_service.set_verbose(verbose) + + # Assert + self.assertIsInstance(tf_service.set_verbose, type(tf_service.set_verbose)) + self.assertIsInstance(tf_service.cmd.set_verbose, type(tf_service.cmd.set_verbose)) + self.assertEqual(tf_service.cmd.run_cmd.func, verbose_run) + self.assertEqual(tf_service.cmd.run_cmd.args[0], True) + + @parameterized.expand(command_execute_data) + def test_tf_service_set_verbose_False(self, command_execute_data): + + # Arrange + verbose = False + command = Command() + + # Act + for cmd in command_execute_data: + command.append(cmd) + + tf_service = TerraformService(cmd=command) + tf_service.set_verbose(verbose) + + # Assert + self.assertIsInstance(tf_service.set_verbose, type(tf_service.set_verbose)) + self.assertIsInstance(tf_service.cmd.set_verbose, type(tf_service.cmd.set_verbose)) + self.assertEqual(tf_service.cmd.run_cmd.func, verbose_run) + self.assertEqual(tf_service.cmd.run_cmd.args[0], False) + + def test_tf_service_init(self): + + # Arrange + command = Command() + tf_service = TerraformService(cmd=command) + + dir_path = KAOS_STATE_DIR + derived_path = os.path.join(os.getcwd(), KAOS_STATE_DIR) + command_history = [f"terraform init {derived_path} "] + + # Act + tf_service.init(dir_path) + + # Assert + self.assertEqual(tf_service.cmd.history, command_history) + + def test_tf_service_new_workspace(self): + + # Arrange + command = Command() + tf_service = TerraformService(cmd=command) + + env = 'prod' + directory = os.path.join(os.getcwd(), KAOS_STATE_DIR) + command_history = [f"terraform workspace new {env} {directory}"] + + # Act + tf_service.new_workspace(directory, env) + + # Assert + self.assertEqual(tf_service.cmd.history, command_history) + + def test_tf_service_select_workspace(self): + + # Arrange + command = Command() + tf_service = TerraformService(cmd=command) + + env = 'prod' + directory = os.path.join(os.getcwd(), KAOS_STATE_DIR) + command_history = [f"terraform workspace select {env} {directory}"] + + # Act + tf_service.select_workspace(directory, env) + + # Assert + self.assertEqual(tf_service.cmd.history, command_history) + + def test_tf_service_plan(self): + + # Arrange + command = Command() + tf_service = TerraformService(cmd=command) + + env = 'prod' + directory = os.path.join(os.getcwd(), KAOS_STATE_DIR) + command_history = [f"terraform workspace select {env} {directory}"] + + # Act + tf_service.select_workspace(directory, env) + + # Assert + self.assertEqual(tf_service.cmd.history, command_history) + + + + + + + + + + + + + + + diff --git a/cli/kaos_cli/utils/tests/test_validation.py b/cli/kaos_cli/utils/tests/test_validation.py index 89adc08..e73317d 100644 --- a/cli/kaos_cli/utils/tests/test_validation.py +++ b/cli/kaos_cli/utils/tests/test_validation.py @@ -10,6 +10,7 @@ def test_validate_input(): with pytest.raises(MissingArgumentError): validate_inputs([None, None], ["a, b"]) + @mock.patch('socket.socket') def test_validate_unused_port_returns_true_when_port_is_unused(socket_mock): # Arrange @@ -26,6 +27,7 @@ def test_validate_unused_port_returns_true_when_port_is_unused(socket_mock): assert is_available is True mocked_socket_obj.bind.assert_called_once_with((host_arg, port_arg)) + @mock.patch('socket.socket') def test_validate_unused_port_returns_false_when_port_is_already_in_use(socket_mock): # Arrange diff --git a/cli/requirements.txt b/cli/requirements.txt index 343eb35..458b6ef 100644 --- a/cli/requirements.txt +++ b/cli/requirements.txt @@ -8,4 +8,6 @@ tqdm==4.32.2 dataclasses-json==0.2.14 kaos-model==1.0.0 requests_toolbelt==0.9.1 -configobj==5.0.6 \ No newline at end of file +configobj==5.0.6 +parameterized==0.7.1 + From b21f8c198ab27a034016b1fb840fcde37e2c3bdf Mon Sep 17 00:00:00 2001 From: Shankar M S Date: Tue, 26 Nov 2019 11:07:46 +0100 Subject: [PATCH 02/13] [WIP] k-82 tests more tf_service tests --- cli/kaos_cli/services/terraform_service.py | 3 +- .../services/tests/test_tf_service.py | 83 +++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/cli/kaos_cli/services/terraform_service.py b/cli/kaos_cli/services/terraform_service.py index 2cf26a0..350ecf2 100644 --- a/cli/kaos_cli/services/terraform_service.py +++ b/cli/kaos_cli/services/terraform_service.py @@ -54,7 +54,8 @@ def destroy(self, directory, extra_vars): f"{extra_vars} --auto-approve {directory}") def execute(self): - self.cmd.execute() + exitcode, out, err = self.cmd.execute() + return exitcode, out, err def cd_dir(self, build_dir): self.cmd.append(f'cd {build_dir}') diff --git a/cli/kaos_cli/services/tests/test_tf_service.py b/cli/kaos_cli/services/tests/test_tf_service.py index 64bc238..2cc10e6 100644 --- a/cli/kaos_cli/services/tests/test_tf_service.py +++ b/cli/kaos_cli/services/tests/test_tf_service.py @@ -224,6 +224,89 @@ def test_tf_service_plan(self): # Assert self.assertEqual(tf_service.cmd.history, command_history) + def test_tf_service_apply(self): + + # Arrange + command = Command() + tf_service = TerraformService(cmd=command) + + extra_vars = 'prod' + directory = os.path.join(os.getcwd(), KAOS_STATE_DIR) + command_history = [f"terraform apply --var-file={directory}/terraform.tfvars {extra_vars} " + f"--auto-approve {directory}"] + + # Act + tf_service.apply(directory, extra_vars) + + # Assert + self.assertEqual(tf_service.cmd.history, command_history) + + def test_tf_service_destroy(self): + + # Arrange + command = Command() + tf_service = TerraformService(cmd=command) + + extra_vars = 'prod' + directory = os.path.join(os.getcwd(), KAOS_STATE_DIR) + command_history = [f"terraform destroy --var-file={directory}/terraform.tfvars {extra_vars} --auto-approve " + f"{directory}"] + + # Act + tf_service.destroy(directory, extra_vars) + + # Assert + self.assertEqual(tf_service.cmd.history, command_history) + + def test_tf_service_destroy(self): + + # Arrange + command = Command() + tf_service = TerraformService(cmd=command) + + extra_vars = 'prod' + directory = os.path.join(os.getcwd(), KAOS_STATE_DIR) + command_history = [f"terraform destroy --var-file={directory}/terraform.tfvars {extra_vars} --auto-approve " + f"{directory}"] + + # Act + tf_service.destroy(directory, extra_vars) + + # Assert + self.assertEqual(tf_service.cmd.history, command_history) + + @parameterized.expand(command_execute_data) + def test_tf_service_execute(self, command_execute_data): + + # Arrange + command = Command() + + # Act + for cmd in command_execute_data: + command.append(cmd) + tf_service = TerraformService(cmd=command) + exitcode, out, err = tf_service.execute() + + # Assert + self.assertEqual(exitcode, 0) + + def test_tf_service_cd_dir(self): + + # Arrange + command = Command() + tf_service = TerraformService(cmd=command) + + directory = os.path.join(os.getcwd(), KAOS_STATE_DIR) + command_history = [f"cd {directory}"] + + # Act + tf_service.cd_dir(directory) + + # Assert + self.assertEqual(tf_service.cmd.history, command_history) + + + From 9777c09efe4e246e99fe4edc8c18ad3d981f5df0 Mon Sep 17 00:00:00 2001 From: Shankar M S Date: Wed, 27 Nov 2019 14:19:34 +0100 Subject: [PATCH 03/13] removed unused imports --- cli/kaos_cli/services/tests/test_tf_service.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cli/kaos_cli/services/tests/test_tf_service.py b/cli/kaos_cli/services/tests/test_tf_service.py index 2cc10e6..7448827 100644 --- a/cli/kaos_cli/services/tests/test_tf_service.py +++ b/cli/kaos_cli/services/tests/test_tf_service.py @@ -1,15 +1,11 @@ import os -import pytest from parameterized import parameterized -import logging -import subprocess -from unittest import TestCase, mock +from unittest import TestCase from kaos_cli.services.terraform_service import TerraformService -from kaos_cli.services.tests import create_terraform_service from kaos_cli.services.terraform_service import Command -from kaos_cli.utils.helpers import verbose_run, run_cmd +from kaos_cli.utils.helpers import verbose_run from kaos_cli.constants import KAOS_STATE_DIR From 88c40aecb53108b33559f64454f4c93a34b9ab0b Mon Sep 17 00:00:00 2001 From: Shankar M S Date: Wed, 27 Nov 2019 14:19:57 +0100 Subject: [PATCH 04/13] added tests for state service --- .../services/tests/test_state_service.py | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 cli/kaos_cli/services/tests/test_state_service.py diff --git a/cli/kaos_cli/services/tests/test_state_service.py b/cli/kaos_cli/services/tests/test_state_service.py new file mode 100644 index 0000000..0dd6655 --- /dev/null +++ b/cli/kaos_cli/services/tests/test_state_service.py @@ -0,0 +1,33 @@ +import os +from parameterized import parameterized + +from unittest import TestCase + +from kaos_cli.services.state_service import StateService + + +def state_service_test_inputs(): + return [ + ( + [('context1', 'section1', 'param1')] + ), + ] + + +class TestStateService(TestCase): + + @parameterized.expand(state_service_test_inputs) + def test_state_append(self, state_service_test_inputs): + + # Arrange + backend = StateService() + + # Act + for arguments in state_service_test_inputs: + print("arguments", arguments) + backend.create() + backend.set() + backend.get() + + # Assert + self.assertEqual(0, 0) From 99d5a9328a707f2c21f317baf3eb0357a02bd3f7 Mon Sep 17 00:00:00 2001 From: Shankar M S Date: Thu, 28 Nov 2019 19:45:02 +0100 Subject: [PATCH 05/13] k-91 state_service unit tests completed --- Pipfile.lock | 42 ++-- .../services/tests/test_state_service.py | 203 +++++++++++++++++- 2 files changed, 215 insertions(+), 30 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 3614333..5eebce3 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -18,10 +18,10 @@ "default": { "certifi": { "hashes": [ - "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", - "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" + "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", + "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" ], - "version": "==2019.9.11" + "version": "==2019.11.28" }, "chardet": { "hashes": [ @@ -222,10 +222,10 @@ }, "certifi": { "hashes": [ - "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", - "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" + "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", + "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" ], - "version": "==2019.9.11" + "version": "==2019.11.28" }, "cgroupspy": { "hashes": [ @@ -500,19 +500,19 @@ }, "psutil": { "hashes": [ - "sha256:021d361439586a0fd8e64f8392eb7da27135db980f249329f1a347b9de99c695", - "sha256:145e0f3ab9138165f9e156c307100905fd5d9b7227504b8a9d3417351052dc3d", - "sha256:348ad4179938c965a27d29cbda4a81a1b2c778ecd330a221aadc7bd33681afbd", - "sha256:3feea46fbd634a93437b718518d15b5dd49599dfb59a30c739e201cc79bb759d", - "sha256:474e10a92eeb4100c276d4cc67687adeb9d280bbca01031a3e41fb35dfc1d131", - "sha256:47aeb4280e80f27878caae4b572b29f0ec7967554b701ba33cd3720b17ba1b07", - "sha256:73a7e002781bc42fd014dfebb3fc0e45f8d92a4fb9da18baea6fb279fbc1d966", - "sha256:d051532ac944f1be0179e0506f6889833cf96e466262523e57a871de65a15147", - "sha256:dfb8c5c78579c226841908b539c2374da54da648ee5a837a731aa6a105a54c00", - "sha256:e3f5f9278867e95970854e92d0f5fe53af742a7fc4f2eba986943345bcaed05d", - "sha256:e9649bb8fc5cea1f7723af53e4212056a6f984ee31784c10632607f472dec5ee" + "sha256:094f899ac3ef72422b7e00411b4ed174e3c5a2e04c267db6643937ddba67a05b", + "sha256:10b7f75cc8bd676cfc6fa40cd7d5c25b3f45a0e06d43becd7c2d2871cbb5e806", + "sha256:1b1575240ca9a90b437e5a40db662acd87bbf181f6aa02f0204978737b913c6b", + "sha256:21231ef1c1a89728e29b98a885b8e0a8e00d09018f6da5cdc1f43f988471a995", + "sha256:28f771129bfee9fc6b63d83a15d857663bbdcae3828e1cb926e91320a9b5b5cd", + "sha256:70387772f84fa5c3bb6a106915a2445e20ac8f9821c5914d7cbde148f4d7ff73", + "sha256:b560f5cd86cf8df7bcd258a851ca1ad98f0d5b8b98748e877a0aec4e9032b465", + "sha256:b74b43fecce384a57094a83d2778cdfc2e2d9a6afaadd1ebecb2e75e0d34e10d", + "sha256:e85f727ffb21539849e6012f47b12f6dd4c44965e56591d8dec6e8bc9ab96f4a", + "sha256:fd2e09bb593ad9bdd7429e779699d2d47c1268cbde4dda95fcd1bd17544a0217", + "sha256:ffad8eb2ac614518bbe3c0b8eb9dffdb3a8d2e3a7d5da51c5b974fb723a5c5aa" ], - "version": "==5.6.5" + "version": "==5.6.7" }, "py": { "hashes": [ @@ -536,10 +536,10 @@ }, "pytest": { "hashes": [ - "sha256:1897d74f60a5d8be02e06d708b41bf2445da2ee777066bd68edf14474fc201eb", - "sha256:f6a567e20c04259d41adce9a360bd8991e6aa29dd9695c5e6bd25a9779272673" + "sha256:63344a2e3bce2e4d522fd62b4fdebb647c019f1f9e4ca075debbd13219db4418", + "sha256:f67403f33b2b1d25a6756184077394167fe5e2f9d8bdaab30707d19ccec35427" ], - "version": "==5.3.0" + "version": "==5.3.1" }, "pytest-mock": { "hashes": [ diff --git a/cli/kaos_cli/services/tests/test_state_service.py b/cli/kaos_cli/services/tests/test_state_service.py index 0dd6655..8f5d6a7 100644 --- a/cli/kaos_cli/services/tests/test_state_service.py +++ b/cli/kaos_cli/services/tests/test_state_service.py @@ -1,33 +1,218 @@ import os from parameterized import parameterized +from configobj import ConfigObj from unittest import TestCase from kaos_cli.services.state_service import StateService +from kaos_cli.constants import CONFIG_PATH, KAOS_STATE_DIR def state_service_test_inputs(): return [ ( - [('context1', 'section1', 'param1')] + 'context1', 'param1' ), + ( + 'context2', 'param2' + ), + ( + '', 'param3' + ), + ( + 'context4', '' + ), + ( + '', '' + ), + ( + {}, 'param6' + ), + ( + 'context7', {} + ), + ( + {}, {} + ), + ( + '', {} + ), + ( + {}, '' + ), + ( + None, 'param11' + ), + ( + 'context11', None + ), + ( + None, None + ), + ( + {}, None + ), + ( + None, {} + ), + ( + '', None + ), + ( + None, '' + ), + ( + 1, 'param18' + ), + ( + 'context', 2 + ), + ( + 3, {} + ), + ( + {}, 4 + ), + ( + 5, '' + ), + ( + '', 6 + ), + ( + 7, None + ), + ( + None, 8 + ), + ] class TestStateService(TestCase): + # Arrange + TestCase.backend = StateService() + TestCase.switch = False + + def test_state_service_create(self): + + # Act + TestCase.backend.create() + + # Assert + self.assertTrue(os.path.exists(KAOS_STATE_DIR)) + + def test_state_service_is_created(self): + + # Act + TestCase.backend.is_created(KAOS_STATE_DIR) + + # Assert + self.assertEqual(True, TestCase.backend.is_created(KAOS_STATE_DIR)) + + def test_state_service_list_providers(self): + + # Act + provider_list = TestCase.backend.list_providers() + + # Assert + self.assertEqual([], provider_list) + + @parameterized.expand(state_service_test_inputs) + def test_state_service_set_and_get(self, context, param): + + # Arrange + if not isinstance(context, str): + TestCase.switch = True + if context is None: + context = {} + else: + context = str(context) + + # Act + TestCase.backend.set('section', context=context) + + # Assert + self.assertEqual(context, TestCase.backend.config['section']['context']) + + # Act + TestCase.backend.get('section', 'context') + + # Assert + self.assertEqual(context, TestCase.backend.config['section']['context']) + + @parameterized.expand(state_service_test_inputs) + def test_state_service_set_and_get_sections(self, context, param): + + # Arrange + if not isinstance(param, str): + TestCase.switch = True + if param is None: + param = {} + else: + param = str(context) + + # Act + TestCase.backend.set_section('section', 'subsection', param=param) + + # Assert + self.assertEqual(param, TestCase.backend.config['section']['subsection']['param']) + + # Act + TestCase.backend.get_section('section', 'subsection', 'param') + @parameterized.expand(state_service_test_inputs) - def test_state_append(self, state_service_test_inputs): + def test_state_service_write(self, context, param): + + # Act + TestCase.backend.write() + + # Assert + self.assertEqual(TestCase.backend.config, ConfigObj(CONFIG_PATH)) + + def test_state_service_has_section(self): # Arrange - backend = StateService() + if not TestCase.switch: + # Act + TestCase.backend.has_section('section', 'subsection') + + # Assert + self.assertEqual(TestCase.backend.config['section']['subsection'], + TestCase.backend.has_section('section', 'subsection')) + + # Act + TestCase.backend.remove_section('section', 'subsection') + + # Assert + self.assertEqual("removed", + "removed" if 'subsection' not in TestCase.backend.config['section'] else "not removed") + + def test_state_service_remove(self): + + # Act + TestCase.backend.remove('section') + + # Assert + self.assertEqual("removed", "removed" if 'section' not in TestCase.backend.config else "not removed") + + def test_state_service_provider_delete(self): # Act - for arguments in state_service_test_inputs: - print("arguments", arguments) - backend.create() - backend.set() - backend.get() + TestCase.backend.provider_delete(CONFIG_PATH) # Assert - self.assertEqual(0, 0) + self.assertTrue(not os.path.exists(CONFIG_PATH)) + + + + + + + + + + + + From 2e5d9bdf117d85e9cfef41c84eabfa8a8ddb8a3b Mon Sep 17 00:00:00 2001 From: Shankar M S Date: Mon, 2 Dec 2019 16:09:03 +0100 Subject: [PATCH 06/13] refactor state service tests --- .../services/tests/test_state_service.py | 16 +++++++++++++--- cli/kaos_cli/utils/validators.py | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/cli/kaos_cli/services/tests/test_state_service.py b/cli/kaos_cli/services/tests/test_state_service.py index 8f5d6a7..c3380a5 100644 --- a/cli/kaos_cli/services/tests/test_state_service.py +++ b/cli/kaos_cli/services/tests/test_state_service.py @@ -1,4 +1,5 @@ import os +import time from parameterized import parameterized from configobj import ConfigObj @@ -162,8 +163,11 @@ def test_state_service_set_and_get_sections(self, context, param): # Act TestCase.backend.get_section('section', 'subsection', 'param') - @parameterized.expand(state_service_test_inputs) - def test_state_service_write(self, context, param): + # Assert + self.assertEqual(TestCase.backend.config['section']['subsection'], + TestCase.backend.has_section('section', 'subsection')) + + def test_state_service_write(self): # Act TestCase.backend.write() @@ -171,9 +175,13 @@ def test_state_service_write(self, context, param): # Assert self.assertEqual(TestCase.backend.config, ConfigObj(CONFIG_PATH)) - def test_state_service_has_section(self): + @parameterized.expand(state_service_test_inputs) + def test_state_service_has_section(self, context, param): # Arrange + TestCase.backend.set('section', context=context) + TestCase.backend.set_section('section', 'subsection', param=param) + if not TestCase.switch: # Act TestCase.backend.has_section('section', 'subsection') @@ -216,3 +224,5 @@ def test_state_service_provider_delete(self): + + diff --git a/cli/kaos_cli/utils/validators.py b/cli/kaos_cli/utils/validators.py index 2b7065b..1669e44 100644 --- a/cli/kaos_cli/utils/validators.py +++ b/cli/kaos_cli/utils/validators.py @@ -13,7 +13,7 @@ class EnvironmentState: """ - This class is used to validate existence of already built environmnets + This class is used to validate existence of already built environments """ def __init__(self): self.cloud = None From b31bc79bb4f1d47a53416c8857b9910777bec399 Mon Sep 17 00:00:00 2001 From: Shankar M S Date: Tue, 21 Jan 2020 18:10:44 +0100 Subject: [PATCH 07/13] [WIP] backend_facade unit tests --- cli/kaos_cli/constants.py | 2 + cli/kaos_cli/services/state_service.py | 4 +- .../services/tests/test_state_service.py | 52 +++++++++---------- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/cli/kaos_cli/constants.py b/cli/kaos_cli/constants.py index 26ea474..8b7e380 100644 --- a/cli/kaos_cli/constants.py +++ b/cli/kaos_cli/constants.py @@ -98,3 +98,5 @@ CONTEXTS = 'contexts' ACTIVE = 'active' REMOTE = 'remote' + +TEST_CONFIG_PATH = os.path.join(KAOS_HOME, 'kaos_cli', 'facades', 'tests', 'fixtures', 'config') diff --git a/cli/kaos_cli/services/state_service.py b/cli/kaos_cli/services/state_service.py index 9afe325..0a6a121 100644 --- a/cli/kaos_cli/services/state_service.py +++ b/cli/kaos_cli/services/state_service.py @@ -8,8 +8,8 @@ class StateService: - def __init__(self, config=None): - self.config = config or ConfigObj(CONFIG_PATH) + def __init__(self): + self.config = ConfigObj(CONFIG_PATH) def set(self, section, **kwargs): self.config[section] = kwargs diff --git a/cli/kaos_cli/services/tests/test_state_service.py b/cli/kaos_cli/services/tests/test_state_service.py index c3380a5..ed12ee1 100644 --- a/cli/kaos_cli/services/tests/test_state_service.py +++ b/cli/kaos_cli/services/tests/test_state_service.py @@ -93,13 +93,13 @@ def state_service_test_inputs(): class TestStateService(TestCase): # Arrange - TestCase.backend = StateService() + TestCase.state_service = StateService() TestCase.switch = False def test_state_service_create(self): # Act - TestCase.backend.create() + TestCase.state_service.create() # Assert self.assertTrue(os.path.exists(KAOS_STATE_DIR)) @@ -107,15 +107,15 @@ def test_state_service_create(self): def test_state_service_is_created(self): # Act - TestCase.backend.is_created(KAOS_STATE_DIR) + TestCase.state_service.is_created(KAOS_STATE_DIR) # Assert - self.assertEqual(True, TestCase.backend.is_created(KAOS_STATE_DIR)) + self.assertEqual(True, TestCase.state_service.is_created(KAOS_STATE_DIR)) def test_state_service_list_providers(self): # Act - provider_list = TestCase.backend.list_providers() + provider_list = TestCase.state_service.list_providers() # Assert self.assertEqual([], provider_list) @@ -132,16 +132,16 @@ def test_state_service_set_and_get(self, context, param): context = str(context) # Act - TestCase.backend.set('section', context=context) + TestCase.state_service.set('section', context=context) # Assert - self.assertEqual(context, TestCase.backend.config['section']['context']) + self.assertEqual(context, TestCase.state_service.config['section']['context']) # Act - TestCase.backend.get('section', 'context') + TestCase.state_service.get('section', 'context') # Assert - self.assertEqual(context, TestCase.backend.config['section']['context']) + self.assertEqual(context, TestCase.state_service.config['section']['context']) @parameterized.expand(state_service_test_inputs) def test_state_service_set_and_get_sections(self, context, param): @@ -155,60 +155,60 @@ def test_state_service_set_and_get_sections(self, context, param): param = str(context) # Act - TestCase.backend.set_section('section', 'subsection', param=param) + TestCase.state_service.set_section('section', 'subsection', param=param) # Assert - self.assertEqual(param, TestCase.backend.config['section']['subsection']['param']) + self.assertEqual(param, TestCase.state_service.config['section']['subsection']['param']) # Act - TestCase.backend.get_section('section', 'subsection', 'param') + TestCase.state_service.get_section('section', 'subsection', 'param') # Assert - self.assertEqual(TestCase.backend.config['section']['subsection'], - TestCase.backend.has_section('section', 'subsection')) + self.assertEqual(TestCase.state_service.config['section']['subsection'], + TestCase.state_service.has_section('section', 'subsection')) def test_state_service_write(self): # Act - TestCase.backend.write() + TestCase.state_service.write() # Assert - self.assertEqual(TestCase.backend.config, ConfigObj(CONFIG_PATH)) + self.assertEqual(TestCase.state_service.config, ConfigObj(CONFIG_PATH)) @parameterized.expand(state_service_test_inputs) def test_state_service_has_section(self, context, param): # Arrange - TestCase.backend.set('section', context=context) - TestCase.backend.set_section('section', 'subsection', param=param) + TestCase.state_service.set('section', context=context) + TestCase.state_service.set_section('section', 'subsection', param=param) if not TestCase.switch: # Act - TestCase.backend.has_section('section', 'subsection') + TestCase.state_service.has_section('section', 'subsection') # Assert - self.assertEqual(TestCase.backend.config['section']['subsection'], - TestCase.backend.has_section('section', 'subsection')) + self.assertEqual(TestCase.state_service.config['section']['subsection'], + TestCase.state_service.has_section('section', 'subsection')) # Act - TestCase.backend.remove_section('section', 'subsection') + TestCase.state_service.remove_section('section', 'subsection') # Assert self.assertEqual("removed", - "removed" if 'subsection' not in TestCase.backend.config['section'] else "not removed") + "removed" if 'subsection' not in TestCase.state_service.config['section'] else "not removed") def test_state_service_remove(self): # Act - TestCase.backend.remove('section') + TestCase.state_service.remove('section') # Assert - self.assertEqual("removed", "removed" if 'section' not in TestCase.backend.config else "not removed") + self.assertEqual("removed", "removed" if 'section' not in TestCase.state_service.config else "not removed") def test_state_service_provider_delete(self): # Act - TestCase.backend.provider_delete(CONFIG_PATH) + TestCase.state_service.provider_delete(CONFIG_PATH) # Assert self.assertTrue(not os.path.exists(CONFIG_PATH)) From cdb65b32dfa8403e17a0eaea49e7df306b65ca80 Mon Sep 17 00:00:00 2001 From: Shankar M S Date: Thu, 23 Jan 2020 11:00:50 +0100 Subject: [PATCH 08/13] test_backend_facade completed --- .../facades/tests/test_backend_facade.py | 368 ++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 cli/kaos_cli/facades/tests/test_backend_facade.py diff --git a/cli/kaos_cli/facades/tests/test_backend_facade.py b/cli/kaos_cli/facades/tests/test_backend_facade.py new file mode 100644 index 0000000..8727003 --- /dev/null +++ b/cli/kaos_cli/facades/tests/test_backend_facade.py @@ -0,0 +1,368 @@ +from parameterized import parameterized +import re +from unittest import TestCase + +from kaos_cli.facades.backend_facade import BackendFacade +from kaos_cli.services.terraform_service import TerraformService +from kaos_cli.services.state_service import StateService +from kaos_cli.services.terraform_service import Command +from kaos_cli.constants import CONFIG_PATH, ACTIVE, DEFAULT, CONTEXTS + + +def backend_facade_test_inputs(): + return [ + ( + 'DOCKER', 'backend', 'url', 'token', 'infrastructure', 'kubeconfig', 'user' + ), + ( + 'GCP', 'backend', 'url', 'token', 'infrastructure', 'kubeconfig', 'user' + ), + ( + 'AWS', 'backend', 'url', 'token', 'infrastructure', 'kubeconfig', 'user' + ), + ( + 'Remote1', 'backend', 'url', 'token', 'infrastructure', 'kubeconfig', 'user' + ), + ] + + +class TestBackendFacade(TestCase): + + @staticmethod + def derive_context(cloud): + env_list = ['', 'dev', 'stage', 'prod'] + for env in env_list: + return cloud + '_' + env + + def manipulate_context_list(self, context_list): + self.state_service.set(CONTEXTS, environments=context_list) + + # Arrange + TestCase.state_service = StateService() + TestCase.command = Command() + TestCase.tf_service = TerraformService(cmd=TestCase.command) + + def arrange_test_fixtures(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.state_service.set(ACTIVE, environment=environment) + self.state_service.set(CONTEXTS, environments=environment) + self.state_service.set(DEFAULT, user=user) + self.state_service.set(environment) + self.state_service.set_section(environment, backend, url=url, token=token) + self.state_service.set_section(environment, infra, kubeconfig=kubeconfig) + self.facade = BackendFacade(TestCase.state_service, TestCase.tf_service) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_get_active_context(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + test_inputs_active_contexts = [None, '', environment] + + for env in test_inputs_active_contexts: + self.state_service.set(ACTIVE, environment=env) + + # Act + active_context = self.facade.get_active_context() + + # Assert + self.assertEqual(active_context, self.facade.state_service.get(ACTIVE, 'environment')) + + @parameterized.expand(backend_facade_test_inputs) + def test_property_active_context(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + active_context_property = self.facade.active_context + + # Assert + self.assertEqual(active_context_property, environment) + + @parameterized.expand(backend_facade_test_inputs) + def test_property_url(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + url_property = self.facade.url + + # Assert + self.assertEqual(url_property, url) + + @parameterized.expand(backend_facade_test_inputs) + def test_property_user(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + user_property = self.facade.user + + # Assert + self.assertEqual(user_property, user) + + @parameterized.expand(backend_facade_test_inputs) + def test_property_token(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + token_property = self.facade.token + + # Assert + self.assertEqual(token_property, token) + + @parameterized.expand(backend_facade_test_inputs) + def test_property_kubeconfig(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + kubeconfig_property = self.facade.kubeconfig + + # Assert + self.assertEqual(kubeconfig_property, kubeconfig) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_init(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + ## TODO: Rectify the following assertions after fixing the dir_build path for init() after merging PR #95 + # self.facade.init(url, token) + + # Assert + self.assertEqual(0, 0) + self.assertEqual(1, 1) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_list(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + list_result = self.facade.list() + context = list_result[0]['context'] + + # Assert + self.assertEqual(context, environment) + + # Arrange (modify the contexts list) + test_inputs = [None, ['DOCKER', 'GCP', 'AWS']] + for test_input in test_inputs: + self.state_service.set(CONTEXTS, environments=test_input) + + # Act + list_result = self.facade.list() + + if len(list_result) > 0: + context = [x['context'] for x in list_result] + else: + context = list_result + test_input = [] + + # Assert + print("context", context) + self.assertEqual(context, test_input) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_get_active_context(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + active_context = self.facade.get_active_context() + + # Assert + self.assertEqual(active_context, environment) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_get_context_info(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + index = 0 + cloud_env = self.derive_context(environment) + + # Act + context_info = self.facade.get_context_info(cloud_env, index) + provider = context_info['provider'] + + # Assert + self.assertEqual(provider, environment) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_get_context_by_index(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + index = 0 + + cloud_env = self.derive_context(environment) + + context_info = self.facade.get_context_info(cloud_env, index) + + # Act + context = self.facade.get_context_by_index([context_info], index) + + # Assert + self.assertEqual(context, cloud_env) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_jsonify_context_list(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + cloud_env = self.derive_context(environment) + + # Act + context_info = self.facade.jsonify_context_list(cloud_env) + provider = context_info[0]['provider'] + + # Assert + self.assertEqual(provider, environment) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_set_context_by_context(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + self.facade.state_service.create() + with open(CONFIG_PATH, 'wb') as f: + f.close() + + # Act + is_set = self.facade.set_context_by_context(environment) + + # Assert + self.assertTrue(is_set) + + # Act + is_set = self.facade.set_context_by_context('invalid_environment') + + # Assert + self.assertFalse(is_set) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_set_context_by_index(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + valid_index = 0 + invalid_index = 1 + + # Act + is_set, current_context = self.facade.set_context_by_index(valid_index) + + # Assert + self.assertTrue(is_set) + self.assertEqual(current_context, environment) + + # Act + is_set, current_context = self.facade.set_context_by_index(invalid_index) + + # Assert + self.assertFalse(is_set) + self.assertIsNone(current_context) + + def test_remove_build_files(self): + pass + + @parameterized.expand(backend_facade_test_inputs) + def test_method_set_context_list(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + self.facade._set_context_list(environment) + list_result = self.facade.list() + contexts = [x['provider'] for x in list_result] + + # Assert + self.assertIn(environment, contexts) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_unset_context_list(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + self.facade._unset_context_list(environment) + list_result = self.facade.list() + contexts = [x['provider'] for x in list_result] + + # Assert + self.assertNotIn(environment, contexts) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_set_active_context(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + self.facade._set_active_context(environment) + active_context = self.facade.state_service.get(ACTIVE, 'environment') + + # Assert + self.assertEqual(active_context, environment) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_remove_section(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + self.facade._remove_section(environment) + config = self.facade.state_service.config + + # Assert + self.assertNotIn(environment, config) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_remove_section(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + # Act + self.facade._remove_section(environment) + config = self.facade.state_service.config + + # Assert + self.assertNotIn(environment, config) + + @parameterized.expand(backend_facade_test_inputs) + def test_method_deactivate_context(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + + self.facade.state_service.create() + with open(CONFIG_PATH, 'wb') as f: + f.close() + + # Act + self.facade._deactivate_context() + active_context = self.facade.state_service.get(ACTIVE, 'environment') + + # Assert + self.assertIsNone(active_context) + + + + + + + + + + + + + + + + + + + + + + From c1c4ddd802fbc6416b935fa6fa84220db56e7fe9 Mon Sep 17 00:00:00 2001 From: KI-labs Date: Mon, 27 Jan 2020 10:00:17 +0000 Subject: [PATCH 09/13] Version updated to: 1.1.4 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 9c1218c..1b87bcd 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.3 \ No newline at end of file +1.1.4 \ No newline at end of file From 13b353a6158209f616eca72e5d3eb38e57384141 Mon Sep 17 00:00:00 2001 From: Shankar M S Date: Tue, 28 Jan 2020 22:11:41 +0100 Subject: [PATCH 10/13] review changes + minor refactor --- cli/kaos_cli/facades/backend_facade.py | 2 - .../facades/tests/test_backend_facade.py | 73 ++++---- cli/kaos_cli/services/state_service.py | 4 - .../services/tests/test_state_service.py | 177 +++++++++++------- .../services/tests/test_tf_service.py | 39 +++- 5 files changed, 173 insertions(+), 122 deletions(-) diff --git a/cli/kaos_cli/facades/backend_facade.py b/cli/kaos_cli/facades/backend_facade.py index a7fcbfa..27d8d64 100644 --- a/cli/kaos_cli/facades/backend_facade.py +++ b/cli/kaos_cli/facades/backend_facade.py @@ -13,7 +13,6 @@ from kaos_cli.utils.environment import check_environment from kaos_cli.utils.helpers import build_dir from kaos_cli.utils.validators import EnvironmentState -from kaos_cli.exceptions.handle_exceptions import handle_specific_exception, handle_exception def is_cloud_provider(cloud): @@ -199,7 +198,6 @@ def _remove_build_files(self, dir_build): """ Function to remove backend directory """ - self.state_service.provider_delete(dir_build) if not self.state_service.list_providers(): self.state_service.full_delete(dir_build) diff --git a/cli/kaos_cli/facades/tests/test_backend_facade.py b/cli/kaos_cli/facades/tests/test_backend_facade.py index 8727003..25ba1c0 100644 --- a/cli/kaos_cli/facades/tests/test_backend_facade.py +++ b/cli/kaos_cli/facades/tests/test_backend_facade.py @@ -1,28 +1,24 @@ +import os +import shutil from parameterized import parameterized -import re -from unittest import TestCase +from unittest import TestCase, skip from kaos_cli.facades.backend_facade import BackendFacade from kaos_cli.services.terraform_service import TerraformService from kaos_cli.services.state_service import StateService from kaos_cli.services.terraform_service import Command -from kaos_cli.constants import CONFIG_PATH, ACTIVE, DEFAULT, CONTEXTS +from kaos_cli.constants import CONFIG_PATH, ACTIVE, DEFAULT, CONTEXTS, KAOS_STATE_DIR def backend_facade_test_inputs(): + + common = ('backend', 'url', 'token', 'infrastructure', 'kubeconfig', 'user') + return [ - ( - 'DOCKER', 'backend', 'url', 'token', 'infrastructure', 'kubeconfig', 'user' - ), - ( - 'GCP', 'backend', 'url', 'token', 'infrastructure', 'kubeconfig', 'user' - ), - ( - 'AWS', 'backend', 'url', 'token', 'infrastructure', 'kubeconfig', 'user' - ), - ( - 'Remote1', 'backend', 'url', 'token', 'infrastructure', 'kubeconfig', 'user' - ), + ('DOCKER',) + common, + ('GCP',) + common, + ('AWS',) + common, + ('Remote1',) + common, ] @@ -37,20 +33,22 @@ def derive_context(cloud): def manipulate_context_list(self, context_list): self.state_service.set(CONTEXTS, environments=context_list) - # Arrange - TestCase.state_service = StateService() - TestCase.command = Command() - TestCase.tf_service = TerraformService(cmd=TestCase.command) - def arrange_test_fixtures(self, environment, backend, url, token, infra, kubeconfig, user): # Arrange + # Instantiation + self.state_service = StateService() + self.command = Command() + self.tf_service = TerraformService(cmd=self.command) + + # Arrange + # Initialization self.state_service.set(ACTIVE, environment=environment) self.state_service.set(CONTEXTS, environments=environment) self.state_service.set(DEFAULT, user=user) self.state_service.set(environment) self.state_service.set_section(environment, backend, url=url, token=token) self.state_service.set_section(environment, infra, kubeconfig=kubeconfig) - self.facade = BackendFacade(TestCase.state_service, TestCase.tf_service) + self.facade = BackendFacade(self.state_service, self.tf_service) @parameterized.expand(backend_facade_test_inputs) def test_method_get_active_context(self, environment, backend, url, token, infra, kubeconfig, user): @@ -123,6 +121,7 @@ def test_property_kubeconfig(self, environment, backend, url, token, infra, kube # Assert self.assertEqual(kubeconfig_property, kubeconfig) + @skip("Skipping test for init method") @parameterized.expand(backend_facade_test_inputs) def test_method_init(self, environment, backend, url, token, infra, kubeconfig, user): # Arrange @@ -264,9 +263,6 @@ def test_method_set_context_by_index(self, environment, backend, url, token, inf self.assertFalse(is_set) self.assertIsNone(current_context) - def test_remove_build_files(self): - pass - @parameterized.expand(backend_facade_test_inputs) def test_method_set_context_list(self, environment, backend, url, token, infra, kubeconfig, user): # Arrange @@ -345,24 +341,19 @@ def test_method_deactivate_context(self, environment, backend, url, token, infra # Assert self.assertIsNone(active_context) + @parameterized.expand(backend_facade_test_inputs) + def test_method_remove_build_files(self, environment, backend, url, token, infra, kubeconfig, user): + # Arrange + self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) + test_path = os.path.join(KAOS_STATE_DIR, 'test') + os.mkdir(test_path) + # Act + self.facade._remove_build_files(test_path) + # Assert + self.assertFalse(os.path.exists(test_path)) - - - - - - - - - - - - - - - - - + # Rearrange + shutil.rmtree(test_path, ignore_errors=True) diff --git a/cli/kaos_cli/services/state_service.py b/cli/kaos_cli/services/state_service.py index 0a6a121..4842076 100644 --- a/cli/kaos_cli/services/state_service.py +++ b/cli/kaos_cli/services/state_service.py @@ -45,10 +45,6 @@ def create(): def list_providers(): return [f for f in glob.glob(f'{KAOS_TF_PATH}/**/terraform.tfstate', recursive=True)] - @staticmethod - def provider_delete(dir_build): - shutil.rmtree(dir_build, ignore_errors=True) - @staticmethod def full_delete(dir_build): shutil.rmtree(dir_build, ignore_errors=True) diff --git a/cli/kaos_cli/services/tests/test_state_service.py b/cli/kaos_cli/services/tests/test_state_service.py index ed12ee1..2104b4f 100644 --- a/cli/kaos_cli/services/tests/test_state_service.py +++ b/cli/kaos_cli/services/tests/test_state_service.py @@ -1,6 +1,5 @@ import os -import time -from parameterized import parameterized +from parameterized import parameterized, parameterized_class from configobj import ConfigObj from unittest import TestCase @@ -10,6 +9,15 @@ def state_service_test_inputs(): + + """Returns different combinations of test input data/parameters that are used in the unit tests + :parameter: + + :return: list + a list of tuples consisting of different parameter combinations + Ex: [(context1, param1), (context2, param2)..] + + """ return [ ( 'context1', 'param1' @@ -90,139 +98,178 @@ def state_service_test_inputs(): ] +@parameterized_class(('context', 'param'), state_service_test_inputs()) class TestStateService(TestCase): - # Arrange - TestCase.state_service = StateService() - TestCase.switch = False + def instantiate_service(self): + # Arrange + self.state_service = StateService() + self.switch = False def test_state_service_create(self): + # Arrange + self.instantiate_service() # Act - TestCase.state_service.create() + self.state_service.create() # Assert self.assertTrue(os.path.exists(KAOS_STATE_DIR)) def test_state_service_is_created(self): + # Arrange + self.instantiate_service() # Act - TestCase.state_service.is_created(KAOS_STATE_DIR) + is_created = self.state_service.is_created(KAOS_STATE_DIR) # Assert - self.assertEqual(True, TestCase.state_service.is_created(KAOS_STATE_DIR)) + self.assertEqual(True, is_created) def test_state_service_list_providers(self): + # Arrange + self.instantiate_service() # Act - provider_list = TestCase.state_service.list_providers() + provider_list = self.state_service.list_providers() # Assert self.assertEqual([], provider_list) - @parameterized.expand(state_service_test_inputs) - def test_state_service_set_and_get(self, context, param): + def test_state_service_set(self): + # Arrange + self.instantiate_service() # Arrange - if not isinstance(context, str): - TestCase.switch = True - if context is None: - context = {} + if not isinstance(self.context, str): + self.switch = True + if self.context is None: + self.context = {} else: - context = str(context) + self.context = str(self.context) # Act - TestCase.state_service.set('section', context=context) + self.state_service.set('section', context=self.context) # Assert - self.assertEqual(context, TestCase.state_service.config['section']['context']) + self.assertEqual(self.context, self.state_service.config['section']['context']) + + def test_state_service_get(self): + # Arrange + self.instantiate_service() + + if not isinstance(self.context, str): + self.switch = True + if self.context is None: + self.context = {} + else: + self.context = str(self.context) + + self.state_service.set('section', context=self.context) # Act - TestCase.state_service.get('section', 'context') + self.state_service.get('section', 'context') # Assert - self.assertEqual(context, TestCase.state_service.config['section']['context']) - - @parameterized.expand(state_service_test_inputs) - def test_state_service_set_and_get_sections(self, context, param): + self.assertEqual(self.context, self.state_service.config['section']['context']) + def test_state_service_set_sections(self): # Arrange - if not isinstance(param, str): - TestCase.switch = True - if param is None: - param = {} + self.instantiate_service() + self.state_service.set('section', context=self.context) + + if not isinstance(self.param, str): + self.switch = True + if self.param is None: + self.param = {} else: - param = str(context) + self.param = str(self.context) # Act - TestCase.state_service.set_section('section', 'subsection', param=param) + self.state_service.set_section('section', 'subsection', param=self.param) # Assert - self.assertEqual(param, TestCase.state_service.config['section']['subsection']['param']) + self.assertEqual(self.param, self.state_service.config['section']['subsection']['param']) + + def test_state_service_get_sections(self): + # Arrange + self.instantiate_service() + self.state_service.set('section', context=self.context) + + if not isinstance(self.param, str): + self.switch = True + if self.param is None: + self.param = {} + else: + self.param = str(self.context) + + self.state_service.set_section('section', 'subsection', param=self.param) # Act - TestCase.state_service.get_section('section', 'subsection', 'param') + self.state_service.get_section('section', 'subsection', 'param') # Assert - self.assertEqual(TestCase.state_service.config['section']['subsection'], - TestCase.state_service.has_section('section', 'subsection')) + self.assertEqual(self.state_service.config['section']['subsection'], + self.state_service.has_section('section', 'subsection')) def test_state_service_write(self): + # Arrange + self.instantiate_service() # Act - TestCase.state_service.write() + self.state_service.write() # Assert - self.assertEqual(TestCase.state_service.config, ConfigObj(CONFIG_PATH)) - - @parameterized.expand(state_service_test_inputs) - def test_state_service_has_section(self, context, param): + self.assertEqual(self.state_service.config, ConfigObj(CONFIG_PATH)) + def test_state_service_has_section(self): # Arrange - TestCase.state_service.set('section', context=context) - TestCase.state_service.set_section('section', 'subsection', param=param) + self.instantiate_service() - if not TestCase.switch: - # Act - TestCase.state_service.has_section('section', 'subsection') - - # Assert - self.assertEqual(TestCase.state_service.config['section']['subsection'], - TestCase.state_service.has_section('section', 'subsection')) + self.state_service.set('section', context=self.context) + self.state_service.set_section('section', 'subsection', param=self.param) + if not self.switch: # Act - TestCase.state_service.remove_section('section', 'subsection') + self.state_service.has_section('section', 'subsection') # Assert - self.assertEqual("removed", - "removed" if 'subsection' not in TestCase.state_service.config['section'] else "not removed") + self.assertEqual(self.state_service.config['section']['subsection'], + self.state_service.has_section('section', 'subsection')) def test_state_service_remove(self): + # Arrange + self.instantiate_service() + self.state_service.set('section', context=self.context) # Act - TestCase.state_service.remove('section') + self.state_service.remove('section') # Assert - self.assertEqual("removed", "removed" if 'section' not in TestCase.state_service.config else "not removed") + self.assertEqual("removed", "removed" if 'section' not in self.state_service.config else "not removed") - def test_state_service_provider_delete(self): + def test_state_service_remove_section(self): + # Arrange + self.instantiate_service() + self.state_service.set('section', context=self.context) + self.state_service.set_section('section', 'subsection', param=self.param) # Act - TestCase.state_service.provider_delete(CONFIG_PATH) - - # Assert - self.assertTrue(not os.path.exists(CONFIG_PATH)) - - - - - - - - + self.state_service.remove_section('section', 'subsection') + is_removed = 'subsection' not in self.state_service.config['section'] + self.assertTrue(is_removed) + def test_state_service_full_delete(self): + # Arrange + self.instantiate_service() + test_path = os.path.join(KAOS_STATE_DIR, 'test') + os.mkdir(test_path) + # Act + self.state_service.full_delete(test_path) + # Assert + self.assertTrue(not os.path.exists(test_path)) diff --git a/cli/kaos_cli/services/tests/test_tf_service.py b/cli/kaos_cli/services/tests/test_tf_service.py index 7448827..872704d 100644 --- a/cli/kaos_cli/services/tests/test_tf_service.py +++ b/cli/kaos_cli/services/tests/test_tf_service.py @@ -9,7 +9,17 @@ from kaos_cli.constants import KAOS_STATE_DIR -def command_append_data(): +def test_inputs_append_data(): + + """Returns different combinations of test input data/parameters that are used in the unit tests + :parameter: + + :return: list + a list of tuples consisting of different set of parameter combinations + Ex: [(command1), ([command1, command2]), ([command1, command2, command3])..] + + """ + return [ ( [], @@ -27,7 +37,16 @@ def command_append_data(): ] -def command_execute_data(): +def test_inputs_execute_data(): + + """Returns different combinations of test input data/parameters that are used in the unit tests + :parameter: + + :return: list + a list of tuples consisting of different parameter combinations + Ex: [(command1), ([command1, command2]), ([command1, command2, command3])..] + + """ return [ ( ['echo <---first_echo_command--->', 'echo <--- executing the second echo command --->'], @@ -41,7 +60,7 @@ def command_execute_data(): class TestTerraformService(TestCase): - @parameterized.expand(command_append_data) + @parameterized.expand(test_inputs_append_data) def test_command_append(self, command_append_data): # Arrange @@ -54,7 +73,7 @@ def test_command_append(self, command_append_data): # Assert self.assertEqual(command.history, command_append_data) - @parameterized.expand(command_execute_data) + @parameterized.expand(test_inputs_execute_data) def test_command_execute(self, command_execute_data): # Arrange @@ -69,7 +88,7 @@ def test_command_execute(self, command_execute_data): # Assert self.assertEqual(exitcode, 0) - @parameterized.expand(command_append_data) + @parameterized.expand(test_inputs_append_data) def test_command_clear(self, command_append_data): # Arrange @@ -84,7 +103,7 @@ def test_command_clear(self, command_append_data): # Assert self.assertEqual(command.history, []) - @parameterized.expand(command_execute_data) + @parameterized.expand(test_inputs_execute_data) def test_command_verbose_true(self, command_execute_data): # Arrange @@ -100,7 +119,7 @@ def test_command_verbose_true(self, command_execute_data): self.assertEqual(command.run_cmd.func, verbose_run) self.assertEqual(command.run_cmd.args[0], True) - @parameterized.expand(command_execute_data) + @parameterized.expand(test_inputs_execute_data) def test_command_verbose_false(self, command_execute_data): # Arrange @@ -116,7 +135,7 @@ def test_command_verbose_false(self, command_execute_data): self.assertEqual(command.run_cmd.func, verbose_run) self.assertEqual(command.run_cmd.args[0], False) - @parameterized.expand(command_execute_data) + @parameterized.expand(test_inputs_execute_data) def test_tf_service_set_verbose_True(self, command_execute_data): # Arrange @@ -136,7 +155,7 @@ def test_tf_service_set_verbose_True(self, command_execute_data): self.assertEqual(tf_service.cmd.run_cmd.func, verbose_run) self.assertEqual(tf_service.cmd.run_cmd.args[0], True) - @parameterized.expand(command_execute_data) + @parameterized.expand(test_inputs_execute_data) def test_tf_service_set_verbose_False(self, command_execute_data): # Arrange @@ -271,7 +290,7 @@ def test_tf_service_destroy(self): # Assert self.assertEqual(tf_service.cmd.history, command_history) - @parameterized.expand(command_execute_data) + @parameterized.expand(test_inputs_execute_data) def test_tf_service_execute(self, command_execute_data): # Arrange From 1280f581f28d6350fc9e0250b5af5f23cc879364 Mon Sep 17 00:00:00 2001 From: KI-labs Date: Tue, 28 Jan 2020 21:12:21 +0000 Subject: [PATCH 11/13] Version updated to: 1.1.4 From b679cf047ed452199b813e8edb6fb59ce3b97936 Mon Sep 17 00:00:00 2001 From: Shankar M S Date: Wed, 5 Feb 2020 14:52:19 +0100 Subject: [PATCH 12/13] removed unused switch and mocked file system manipulations --- .../facades/tests/test_backend_facade.py | 49 +++++++++++++------ .../services/tests/test_state_service.py | 45 +++++++++-------- 2 files changed, 60 insertions(+), 34 deletions(-) diff --git a/cli/kaos_cli/facades/tests/test_backend_facade.py b/cli/kaos_cli/facades/tests/test_backend_facade.py index 25ba1c0..c281367 100644 --- a/cli/kaos_cli/facades/tests/test_backend_facade.py +++ b/cli/kaos_cli/facades/tests/test_backend_facade.py @@ -1,5 +1,6 @@ import os -import shutil +import unittest +import mock from parameterized import parameterized from unittest import TestCase, skip @@ -9,10 +10,10 @@ from kaos_cli.services.terraform_service import Command from kaos_cli.constants import CONFIG_PATH, ACTIVE, DEFAULT, CONTEXTS, KAOS_STATE_DIR +common = ('backend', 'url', 'token', 'infrastructure', 'kubeconfig', 'user') -def backend_facade_test_inputs(): - common = ('backend', 'url', 'token', 'infrastructure', 'kubeconfig', 'user') +def backend_facade_test_inputs(): return [ ('DOCKER',) + common, @@ -341,19 +342,39 @@ def test_method_deactivate_context(self, environment, backend, url, token, infra # Assert self.assertIsNone(active_context) - @parameterized.expand(backend_facade_test_inputs) - def test_method_remove_build_files(self, environment, backend, url, token, infra, kubeconfig, user): +class TestBackendFacadeMocked(unittest.TestCase): + + def arrange_test_fixtures(self, environment, backend, url, token, infra, kubeconfig, user): # Arrange - self.arrange_test_fixtures(environment, backend, url, token, infra, kubeconfig, user) - test_path = os.path.join(KAOS_STATE_DIR, 'test') - os.mkdir(test_path) + # Instantiation + self.state_service = StateService() + self.command = Command() + self.tf_service = TerraformService(cmd=self.command) - # Act - self.facade._remove_build_files(test_path) + # Arrange + # Initialization + self.state_service.set(ACTIVE, environment=environment) + self.state_service.set(CONTEXTS, environments=environment) + self.state_service.set(DEFAULT, user=user) + self.state_service.set(environment) + self.state_service.set_section(environment, backend, url=url, token=token) + self.state_service.set_section(environment, infra, kubeconfig=kubeconfig) + self.facade = BackendFacade(self.state_service, self.tf_service) - # Assert - self.assertFalse(os.path.exists(test_path)) + @mock.patch('shutil.rmtree') + def test_method_remove_build_files(self, rm_mock): + # Arrange + environment = "DOCKER" + + ## common = ('backend', 'url', 'token', 'infrastructure', 'kubeconfig', 'user') + self.arrange_test_fixtures(environment, common[0], common[1], common[2], common[3], common[4], common[5]) + test_path = os.path.join(KAOS_STATE_DIR, 'test') + rm_mock.return_value = 'REMOVED' - # Rearrange - shutil.rmtree(test_path, ignore_errors=True) + # Act + self.facade._remove_build_files(test_path) + + # Assert + rm_mock.assert_called_with(test_path, ignore_errors=True) + self.assertEqual(rm_mock.return_value, 'REMOVED') diff --git a/cli/kaos_cli/services/tests/test_state_service.py b/cli/kaos_cli/services/tests/test_state_service.py index 2104b4f..d054d36 100644 --- a/cli/kaos_cli/services/tests/test_state_service.py +++ b/cli/kaos_cli/services/tests/test_state_service.py @@ -1,5 +1,7 @@ import os -from parameterized import parameterized, parameterized_class +import unittest +import mock +from parameterized import parameterized_class from configobj import ConfigObj from unittest import TestCase @@ -104,7 +106,6 @@ class TestStateService(TestCase): def instantiate_service(self): # Arrange self.state_service = StateService() - self.switch = False def test_state_service_create(self): # Arrange @@ -142,7 +143,6 @@ def test_state_service_set(self): # Arrange if not isinstance(self.context, str): - self.switch = True if self.context is None: self.context = {} else: @@ -159,7 +159,6 @@ def test_state_service_get(self): self.instantiate_service() if not isinstance(self.context, str): - self.switch = True if self.context is None: self.context = {} else: @@ -179,7 +178,6 @@ def test_state_service_set_sections(self): self.state_service.set('section', context=self.context) if not isinstance(self.param, str): - self.switch = True if self.param is None: self.param = {} else: @@ -197,7 +195,6 @@ def test_state_service_get_sections(self): self.state_service.set('section', context=self.context) if not isinstance(self.param, str): - self.switch = True if self.param is None: self.param = {} else: @@ -229,13 +226,12 @@ def test_state_service_has_section(self): self.state_service.set('section', context=self.context) self.state_service.set_section('section', 'subsection', param=self.param) - if not self.switch: - # Act - self.state_service.has_section('section', 'subsection') + # Act + self.state_service.has_section('section', 'subsection') - # Assert - self.assertEqual(self.state_service.config['section']['subsection'], - self.state_service.has_section('section', 'subsection')) + # Assert + self.assertEqual(self.state_service.config['section']['subsection'], + self.state_service.has_section('section', 'subsection')) def test_state_service_remove(self): # Arrange @@ -261,15 +257,24 @@ def test_state_service_remove_section(self): self.assertTrue(is_removed) - def test_state_service_full_delete(self): + +class TestStateServiceMocked(unittest.TestCase): + + def instantiate_service(self): # Arrange - self.instantiate_service() - test_path = os.path.join(KAOS_STATE_DIR, 'test') - os.mkdir(test_path) + self.state_service = StateService() - # Act - self.state_service.full_delete(test_path) + @mock.patch('shutil.rmtree') + def test_method_remove_build_files(self, rm_mock): + # Arrange + self.instantiate_service() + test_path = os.path.join(KAOS_STATE_DIR, 'test') + rm_mock.return_value = 'REMOVED' - # Assert - self.assertTrue(not os.path.exists(test_path)) + # Act + self.state_service.full_delete(test_path) + + # Assert + rm_mock.assert_called_with(test_path, ignore_errors=True) + self.assertEqual(rm_mock.return_value, 'REMOVED') From f323369d0d1b5acd4c64aad2f331c75dba7ef550 Mon Sep 17 00:00:00 2001 From: KI-labs Date: Tue, 25 Feb 2020 09:06:58 +0000 Subject: [PATCH 13/13] Version updated to: 1.1.5 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 1b87bcd..314c3d7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.4 \ No newline at end of file +1.1.5 \ No newline at end of file