From 8e926d4e64972fb63d3e8a0ec51fc10fa58865f6 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 14 Dec 2023 11:38:55 +0100 Subject: [PATCH] add file change check to copy_env_files, add test cases for copy_env_files --- pytest_abra/coordinator.py | 2 +- pytest_abra/env_manager.py | 26 +++++-- tests/test_env_manager.py | 137 +++++++++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 tests/test_env_manager.py diff --git a/pytest_abra/coordinator.py b/pytest_abra/coordinator.py index fbbe9cf..6704360 100644 --- a/pytest_abra/coordinator.py +++ b/pytest_abra/coordinator.py @@ -38,7 +38,7 @@ class Coordinator: def prepare_tests(self) -> None: logger.info("calling prepare_tests()") self.DIR.create_all_dirs() - self.ENV.copy_env_files(self.DIR) + self.ENV.copy_env_files(self.ENV.env_files, self.DIR) self.load_test_credentials(self.DIR) def run_tests(self) -> None: diff --git a/pytest_abra/env_manager.py b/pytest_abra/env_manager.py index 8664624..7076268 100644 --- a/pytest_abra/env_manager.py +++ b/pytest_abra/env_manager.py @@ -4,6 +4,8 @@ from typing import TYPE_CHECKING, NamedTuple from dotenv import dotenv_values +from pytest_abra.utils import files_are_same + if TYPE_CHECKING: from pytest_abra import DirManager, Runner @@ -93,11 +95,25 @@ class EnvManager: "Could not resolve test order. This is possibly due to a circular dependency (a on b, b on c, c on a)" ) - def copy_env_files(self, DIR: "DirManager") -> None: - """Copies all env files to STATES/env_files. Files will be renamed to - -- - 00-authentik-login.test.dev.local-it.cloud.env""" + @staticmethod + def copy_env_files(env_files: list[EnvFile], DIR: "DirManager") -> None: + """Copies all env files to STATES/env_files. - for index, env_file in enumerate(self.env_files): + Files will be renamed to --. Example: + 00-authentik-login.test.dev.local-it.cloud.env + + Does nothing when called twice with same env_files. Throws an AssertionError if either + contents or filenames of env_files have changed (probably test rerun with different input)""" + + dir_was_not_empty = len(list(DIR.ENV_FILES.iterdir())) > 0 + + for index, env_file in enumerate(env_files): file_name = "-".join([str(index).zfill(2), env_file.env_type, env_file.env_path.name]) + if dir_was_not_empty: + # check that the copied env files have not changed + present_files = [f.name for f in DIR.ENV_FILES.iterdir()] + assert ( + file_name in present_files and files_are_same(env_file.env_path, DIR.ENV_FILES / file_name) + ), "It appears that you are resuming a test while the input env files have changed. Start a new test instead" + shutil.copy(env_file.env_path, DIR.ENV_FILES / file_name) diff --git a/tests/test_env_manager.py b/tests/test_env_manager.py new file mode 100644 index 0000000..05255f4 --- /dev/null +++ b/tests/test_env_manager.py @@ -0,0 +1,137 @@ +import shutil +from pathlib import Path + +import pytest + +from pytest_abra.dir_manager import DirManager +from pytest_abra.env_manager import EnvManager +from pytest_abra.utils import files_are_same + +ENV_PATHS = [ + Path("envfiles/blog.test.dev.local-it.cloud.env"), # wordpress + Path("envfiles/login.test.dev.local-it.cloud.env"), # authentik + Path("envfiles/login.test.dev.local-it.cloud.env"), # authentik +] + + +@pytest.fixture +def tmp_output(tmp_path_factory: pytest.TempPathFactory) -> Path: + return tmp_path_factory.mktemp("output") + + +@pytest.fixture +def tmp_recipes(tmp_path_factory: pytest.TempPathFactory) -> Path: + return tmp_path_factory.mktemp("recipes") + + +def test_copy_env_files(tmp_output: Path, tmp_recipes: Path): + # create dirs in output + DIR = DirManager(output_dir=tmp_output, session_id="abc", recipes_dir=tmp_recipes) + DIR.create_all_dirs() + + # confirm dir is empty + assert len(list(DIR.ENV_FILES.iterdir())) == 0 + + # copy env files + env_files = EnvManager._get_env_files(ENV_PATHS) + EnvManager.copy_env_files(env_files, DIR) + + # check that each env file is present in DIR.ENV_FILES with correct contents + assert len(list(DIR.ENV_FILES.iterdir())) == len(env_files) + for index, env_path in enumerate(ENV_PATHS): + matching_files = [f for f in DIR.ENV_FILES.iterdir() if index == int(f.name.split("-")[0])] + assert len(matching_files) == 1 + assert files_are_same(env_path, matching_files[0]) + + +def test_copy_env_files_twice(tmp_output: Path, tmp_recipes: Path): + """Copy the same env files twice""" + # create dirs in output + DIR = DirManager(output_dir=tmp_output, session_id="abc", recipes_dir=tmp_recipes) + DIR.create_all_dirs() + + # confirm dir is empty + assert len(list(DIR.ENV_FILES.iterdir())) == 0 + + # copy env files + env_files = EnvManager._get_env_files(ENV_PATHS) + EnvManager.copy_env_files(env_files, DIR) + + # check that each env file is present in DIR.ENV_FILES with correct contents + assert len(list(DIR.ENV_FILES.iterdir())) == len(env_files) + + # copy env files again + EnvManager.copy_env_files(env_files, DIR) + + for index, env_path in enumerate(ENV_PATHS): + matching_files = [f for f in DIR.ENV_FILES.iterdir() if index == int(f.name.split("-")[0])] + assert len(matching_files) == 1 + assert files_are_same(env_path, matching_files[0]) + + +def test_copy_env_files_twice_with_content_change(tmp_output: Path, tmp_recipes: Path, tmp_path: Path): + # copy env files to tmp_path + assert len(list(tmp_path.iterdir())) == 0 + for f in ENV_PATHS: + shutil.copy(f, tmp_path / f.name) + ENV_PATHS_NEW = list(tmp_path.iterdir()) + assert len(ENV_PATHS_NEW) > 0 + + # create dirs in output + DIR = DirManager(output_dir=tmp_output, session_id="abc", recipes_dir=tmp_recipes) + DIR.create_all_dirs() + + # confirm dir is empty + assert len(list(DIR.ENV_FILES.iterdir())) == 0 + + # copy env files from tmp_path to tmp_output + env_files = EnvManager._get_env_files(ENV_PATHS_NEW) + EnvManager.copy_env_files(env_files, DIR) + + # check that each env file is present in DIR.ENV_FILES with correct contents + assert len(list(DIR.ENV_FILES.iterdir())) == len(env_files) + + # change content of one env_file in tmp_path + file_path = next(tmp_path.iterdir()) + with open(file_path, "w") as file: + file.write("This is the new content") + + # copy env files again + with pytest.raises(AssertionError) as excinfo: + EnvManager.copy_env_files(env_files, DIR) + + assert "input env files have changed" in str(excinfo.value) + + +def test_copy_env_files_twice_with_name_change(tmp_output: Path, tmp_recipes: Path, tmp_path: Path): + # copy env files to tmp_path + assert len(list(tmp_path.iterdir())) == 0 + for f in ENV_PATHS: + shutil.copy(f, tmp_path / f.name) + ENV_PATHS_NEW = list(tmp_path.iterdir()) + assert len(ENV_PATHS_NEW) > 0 + + # create dirs in output + DIR = DirManager(output_dir=tmp_output, session_id="abc", recipes_dir=tmp_recipes) + DIR.create_all_dirs() + + # confirm dir is empty + assert len(list(DIR.ENV_FILES.iterdir())) == 0 + + # copy env files from tmp_path to tmp_output + env_files = EnvManager._get_env_files(ENV_PATHS_NEW) + EnvManager.copy_env_files(env_files, DIR) + + # check that each env file is present in DIR.ENV_FILES with correct contents + assert len(list(DIR.ENV_FILES.iterdir())) == len(env_files) + + # change name of one env_file in tmp_path + file_path = next(tmp_path.iterdir()) + file_path.rename(file_path.parent / (file_path.stem + "-other" + file_path.suffix)) + + # copy env files from tmp_path to tmp_output again + with pytest.raises(AssertionError) as excinfo: + env_files = EnvManager._get_env_files(list(tmp_path.iterdir())) + EnvManager.copy_env_files(env_files, DIR) + + assert "input env files have changed" in str(excinfo.value)