From 6a2d0794e889e583d800320a92609e36b98ec802 Mon Sep 17 00:00:00 2001 From: Daniel McKnight Date: Tue, 31 Dec 2024 10:22:45 -0800 Subject: [PATCH] Add unit test coverage for configuration module Fix error in config validation --- pyklatchat_utils/configuration.py | 26 +++++----- tests/test_common.py | 28 ++++++++++ tests/test_configuration.py | 85 +++++++++++++++++++++++++++++-- 3 files changed, 124 insertions(+), 15 deletions(-) diff --git a/pyklatchat_utils/configuration.py b/pyklatchat_utils/configuration.py index 6cd96b0..ac8ab98 100644 --- a/pyklatchat_utils/configuration.py +++ b/pyklatchat_utils/configuration.py @@ -89,23 +89,25 @@ def _init_ovos_config(self): @deprecated("Legacy configuration is deprecated", "0.0.1") def _init_legacy_config(self): - legacy_config_path = os.path.expanduser( - os.environ.get( - f"{self.config_key}_CONFIG", - "~/.local/share/neon/credentials.json" + try: + legacy_config_path = os.path.expanduser( + os.environ.get( + f"{self.config_key}_CONFIG", + "~/.local/share/neon/credentials.json" + ) ) - ) - self.add_new_config_properties( - self.extract_config_from_path(legacy_config_path) - ) - self._config_data = self._config_data[self.config_key] + self.add_new_config_properties( + self.extract_config_from_path(legacy_config_path) + ) + self._config_data = self._config_data[self.config_key] + except KeyError as e: + raise MalformedConfigurationException(e) def validate_provided_configuration(self): for key in self.required_sub_keys: if key not in self._config_data: - return MalformedConfigurationException( - f"Required configuration {key=!r} is missing" - ) + raise MalformedConfigurationException( + f"Required configuration {key=!r} is missing") def add_new_config_properties(self, new_config_dict: dict, at_key: Optional[str] = None): diff --git a/tests/test_common.py b/tests/test_common.py index b705f07..61d5e62 100644 --- a/tests/test_common.py +++ b/tests/test_common.py @@ -1,3 +1,31 @@ +# NEON AI (TM) SOFTWARE, Software Development Kit & Application Development System +# All trademark and other rights reserved by their respective owners +# Copyright 2008-2022 Neongecko.com Inc. +# Authors: Daniel McKnight, Guy Daniels, Elon Gasper, Richard Leeds, +# Regina Bloomstine, Casimiro Ferreira, Andrii Pernatii, Kirill Hrymailo +# BSD-3 +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + from io import BytesIO from unittest import TestCase diff --git a/tests/test_configuration.py b/tests/test_configuration.py index a255f05..22df1c0 100644 --- a/tests/test_configuration.py +++ b/tests/test_configuration.py @@ -1,7 +1,86 @@ +# NEON AI (TM) SOFTWARE, Software Development Kit & Application Development System +# All trademark and other rights reserved by their respective owners +# Copyright 2008-2022 Neongecko.com Inc. +# Authors: Daniel McKnight, Guy Daniels, Elon Gasper, Richard Leeds, +# Regina Bloomstine, Casimiro Ferreira, Andrii Pernatii, Kirill Hrymailo +# BSD-3 +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from this +# software without specific prior written permission. +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + from unittest import TestCase +from unittest.mock import patch + +from pyklatchat_utils.configuration import KlatConfigurationBase +from pyklatchat_utils.exceptions import MalformedConfigurationException + + +class MockConfig(KlatConfigurationBase): + @property + def config_key(self) -> str: + return "MOCK_MODULE" + + @property + def required_sub_keys(self): + return "test", "key" + + +mock_valid_configuration = { + "MOCK_MODULE": {"test": True, + "key": "value", + "extra": "config"}, + "OTHER_MODULE": {} +} + +mock_missing_top_key = { + "OTHER_MODULE": {"test": True, + "key": "value", + "extra": "config"}, +} + +mock_missing_sub_key = { + "MOCK_MODULE": {"key": "value", + "extra": "config"} +} class TestConfiguration(TestCase): - def test_klat_configuration(self): - from pyklatchat_utils.configuration import KlatConfigurationBase - # TODO + @patch("pyklatchat_utils.configuration.Configuration") + def test_valid_klat_configuration(self, config): + config.return_value = mock_valid_configuration + klat_config = MockConfig() + self.assertEqual(klat_config.config_data, + mock_valid_configuration[klat_config.config_key], + klat_config.config_data) + + # TODO: Test add_new_config_properties + + @patch("pyklatchat_utils.configuration.Configuration") + def test_invalid_klat_configuration(self, config): + # Missing module config + config.return_value = mock_missing_top_key + with self.assertRaises(MalformedConfigurationException): + MockConfig() + + # Incomplete module config + config.return_value = mock_missing_sub_key + with self.assertRaises(MalformedConfigurationException): + MockConfig()