diff --git a/src/helpers.py b/src/helpers.py index 686d6a82e277e2879610d590112fb41505188a77..723acbd57fc1fe1c477cb723fd4a39a0db988e0a 100644 --- a/src/helpers.py +++ b/src/helpers.py @@ -201,19 +201,17 @@ def float_round(number: float, decimals: int = 0, round_type: Callable = math.ce return round_type(number * multiplier) / multiplier -def dict_pop(dict: Dict, pop_keys): - pop_keys = to_list(pop_keys) - return {k: v for k, v in dict.items() if k not in pop_keys} - - def list_pop(list_full: list, pop_items): pop_items = to_list(pop_items) if len(pop_items) > 1: return [e for e in list_full if e not in pop_items] else: - list_pop = list_full.copy() - list_pop.remove(pop_items[0]) - return list_pop + l_pop = list_full.copy() + try: + l_pop.remove(pop_items[0]) + except ValueError: + pass + return l_pop def dict_pop(dict_orig: Dict, pop_keys): diff --git a/test/test_helpers.py b/test/test_helpers.py index 07ec244e078f977dca761274260275aab355c183..623c0bf8b1bec735ab422e31c0e5783b5c711a3a 100644 --- a/test/test_helpers.py +++ b/test/test_helpers.py @@ -7,6 +7,8 @@ import mock import numpy as np import pytest +import re + from src.helpers import * @@ -128,32 +130,63 @@ class TestTimeTracking: class TestPrepareHost: - @mock.patch("socket.gethostname", side_effect=["linux-aa9b", "ZAM144", "zam347", "jrtest", "jwtest"]) + @mock.patch("socket.gethostname", side_effect=["linux-aa9b", "ZAM144", "zam347", "jrtest", "jwtest", + "runner-6HmDp9Qd-project-2411-concurrent"]) @mock.patch("os.getlogin", return_value="testUser") @mock.patch("os.path.exists", return_value=True) def test_prepare_host(self, mock_host, mock_user, mock_path): - path = prepare_host() - assert path == "/home/testUser/machinelearningtools/data/toar_daily/" - path = prepare_host() - assert path == "/home/testUser/Data/toar_daily/" - path = prepare_host() - assert path == "/home/testUser/Data/toar_daily/" - path = prepare_host() - assert path == "/p/project/cjjsc42/testUser/DATA/toar_daily/" - path = prepare_host() - assert path == "/p/home/jusers/testUser/juwels/intelliaq/DATA/toar_daily/" + assert prepare_host() == "/home/testUser/machinelearningtools/data/toar_daily/" + assert prepare_host() == "/home/testUser/Data/toar_daily/" + assert prepare_host() == "/home/testUser/Data/toar_daily/" + assert prepare_host() == "/p/project/cjjsc42/testUser/DATA/toar_daily/" + assert prepare_host() == "/p/home/jusers/testUser/juwels/intelliaq/DATA/toar_daily/" + assert prepare_host() == '/home/testUser/machinelearningtools/data/toar_daily/' @mock.patch("socket.gethostname", return_value="NotExistingHostName") @mock.patch("os.getlogin", return_value="zombie21") - def test_error_handling(self, mock_user, mock_host): + def test_error_handling_unknown_host(self, mock_user, mock_host): with pytest.raises(OSError) as e: prepare_host() assert "unknown host 'NotExistingHostName'" in e.value.args[0] - if "runner-6HmDp9Qd-project-2411-concurrent" not in platform.node(): - mock_host.return_value = "linux-aa9b" - with pytest.raises(NotADirectoryError) as e: - prepare_host() - assert "does not exist for host 'linux-aa9b'" in e.value.args[0] + + @mock.patch("os.getlogin", return_value="zombie21") + @mock.patch("src.helpers.check_path_and_create", side_effect=PermissionError) + def test_error_handling(self, mock_cpath, mock_user): + # if "runner-6HmDp9Qd-project-2411-concurrent" not in platform.node(): + # mock_host.return_value = "linux-aa9b" + with pytest.raises(NotADirectoryError) as e: + prepare_host() + assert PyTestRegex(r"path '.*' does not exist for host '.*'\.") == e.value.args[0] + with pytest.raises(NotADirectoryError) as e: + prepare_host(False) + # assert "does not exist for host 'linux-aa9b'" in e.value.args[0] + assert PyTestRegex(r"path '.*' does not exist for host '.*'\.") == e.value.args[0] + + @mock.patch("socket.gethostname", side_effect=["linux-aa9b", "ZAM144", "zam347", "jrtest", "jwtest", + "runner-6HmDp9Qd-project-2411-concurrent"]) + @mock.patch("os.getlogin", side_effect=OSError) + @mock.patch("os.path.exists", return_value=True) + def test_os_error(self, mock_path, mock_user, mock_host): + path = prepare_host() + assert path == "/home/default/machinelearningtools/data/toar_daily/" + path = prepare_host() + assert path == "/home/default/Data/toar_daily/" + path = prepare_host() + assert path == "/home/default/Data/toar_daily/" + path = prepare_host() + assert path == "/p/project/cjjsc42/default/DATA/toar_daily/" + path = prepare_host() + assert path == "/p/home/jusers/default/juwels/intelliaq/DATA/toar_daily/" + path = prepare_host() + assert path == '/home/default/machinelearningtools/data/toar_daily/' + + @mock.patch("socket.gethostname", side_effect=["linux-aa9b"]) + @mock.patch("os.getlogin", return_value="testUser") + @mock.patch("os.path.exists", return_value=False) + @mock.patch("os.makedirs", side_effect=None) + def test_os_path_exists(self, mock_host, mock_user, mock_path, mock_check): + path = prepare_host() + assert path == "/home/testUser/machinelearningtools/data/toar_daily/" class TestSetExperimentName: @@ -170,6 +203,23 @@ class TestSetExperimentName: exp_name, _ = set_experiment_name(experiment_date="2019-11-14") assert exp_name == "2019-11-14_network" + def test_set_expperiment_hourly(self): + exp_name, exp_path = set_experiment_name(sampling="hourly") + assert exp_name == "TestExperiment_hourly" + assert exp_path == os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "TestExperiment_hourly")) + + +class TestSetBootstrapPath: + + def test_bootstrap_path_is_none(self): + bootstrap_path = set_bootstrap_path(None, 'TestDataPath/', 'daily') + assert bootstrap_path == 'TestDataPath/../bootstrap_daily' + + @mock.patch("os.makedirs", side_effect=None) + def test_bootstap_path_is_given(self, mock_makedir): + bootstrap_path = set_bootstrap_path('Test/path/to/boots', None, None) + assert bootstrap_path == 'Test/path/to/boots' + class TestPytestRegex: @@ -221,3 +271,123 @@ class TestFloatRound: assert float_round(-34.9221, 0, math.floor) == -35. assert float_round(-34.9221, 2) == -34.92 assert float_round(-34.9221, 0) == -34. + + +class TestDictPop: + + @pytest.fixture + def custom_dict(self): + return {'a': 1, 'b': 2, 2: 'ab'} + + def test_dict_pop_single(self, custom_dict): + # one out as list + d_pop = dict_pop(custom_dict, [4]) + assert d_pop == custom_dict + # one out as str + d_pop = dict_pop(custom_dict, '4') + assert d_pop == custom_dict + # one in as str + d_pop = dict_pop(custom_dict, 'b') + assert d_pop == {'a': 1, 2: 'ab'} + # one in as list + d_pop = dict_pop(custom_dict, ['b']) + assert d_pop == {'a': 1, 2: 'ab'} + + def test_dict_pop_multiple(self, custom_dict): + # all out (list) + d_pop = dict_pop(custom_dict, [4, 'mykey']) + assert d_pop == custom_dict + # all in (list) + d_pop = dict_pop(custom_dict, ['a', 2]) + assert d_pop == {'b': 2} + # one in one out (list) + d_pop = dict_pop(custom_dict, [2, '10']) + assert d_pop == {'a': 1, 'b': 2} + + def test_dict_pop_missing_argument(self, custom_dict): + with pytest.raises(TypeError) as e: + dict_pop() + assert "dict_pop() missing 2 required positional arguments: 'dict_orig' and 'pop_keys'" in e.value.args[0] + with pytest.raises(TypeError) as e: + dict_pop(custom_dict) + assert "dict_pop() missing 1 required positional argument: 'pop_keys'" in e.value.args[0] + + +class TestListPop: + + @pytest.fixture + def custom_list(self): + return [1, 2, 3, 'a', 'bc'] + + def test_list_pop_single(self, custom_list): + l_pop = list_pop(custom_list, 1) + assert l_pop == [2, 3, 'a', 'bc'] + l_pop = list_pop(custom_list, 'bc') + assert l_pop == [1, 2, 3, 'a'] + l_pop = list_pop(custom_list, 5) + assert l_pop == custom_list + + def test_list_pop_multiple(self, custom_list): + # all in list + l_pop = list_pop(custom_list, [2, 'a']) + assert l_pop == [1, 3, 'bc'] + # one in one out + l_pop = list_pop(custom_list, ['bc', 10]) + assert l_pop == [1, 2, 3, 'a'] + # all out + l_pop = list_pop(custom_list, [10, 'aa']) + assert l_pop == custom_list + + def test_list_pop_missing_argument(self, custom_list): + with pytest.raises(TypeError) as e: + list_pop() + assert "list_pop() missing 2 required positional arguments: 'list_full' and 'pop_items'" in e.value.args[0] + with pytest.raises(TypeError) as e: + list_pop(custom_list) + assert "list_pop() missing 1 required positional argument: 'pop_items'" in e.value.args[0] + + +class TestLogger: + + @pytest.fixture + def logger(self): + return Logger() + + def test_init_default(self): + log = Logger() + assert log.formatter == "%(asctime)s - %(levelname)s: %(message)s [%(filename)s:%(funcName)s:%(lineno)s]" + assert log.log_file == Logger.setup_logging_path() + # assert PyTestRegex( + # ".*machinelearningtools/src/\.{2}/logging/logging_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}\.log") == log.log_file + + def test_setup_logging_path_none(self): + log_file = Logger.setup_logging_path(None) + assert PyTestRegex( + ".*machinelearningtools/src/\.{2}/logging/logging_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}\.log") == log_file + + @mock.patch("os.makedirs", side_effect=None) + def test_setup_logging_path_given(self, mock_makedirs): + path = "my/test/path" + log_path = Logger.setup_logging_path(path) + assert PyTestRegex("my/test/path/logging_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}\.log") == log_path + + def test_logger_console_level0(self, logger): + consol = logger.logger_console(0) + assert isinstance(consol, logging.StreamHandler) + assert consol.level == 0 + formatter = logging.Formatter(logger.formatter) + assert isinstance(formatter, logging.Formatter) + + def test_logger_console_level1(self, logger): + consol = logger.logger_console(1) + assert isinstance(consol, logging.StreamHandler) + assert consol.level == 1 + formatter = logging.Formatter(logger.formatter) + assert isinstance(formatter, logging.Formatter) + + def test_logger_console_level_wrong_type(self, logger): + with pytest.raises(TypeError) as e: + logger.logger_console(1.5) + assert "Level not an integer or a valid string: 1.5" == e.value.args[0] + +