From 3c5f3d6d4901d3423faf6bebd33c993ad0374ed6 Mon Sep 17 00:00:00 2001 From: Chris Sewell Date: Thu, 18 Feb 2021 18:34:01 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=AA=20TESTS:=20add=20=20`config=5Fwith?= =?UTF-8?q?=5Fprofile`=20fixture?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Partially addresses #4249, removing `temporary_config_instance` and `with_temporary_config_instance` from `tests/utils/configuration.py` --- tests/cmdline/commands/test_help.py | 7 +-- tests/cmdline/commands/test_profile.py | 14 ++--- tests/cmdline/commands/test_setup.py | 8 +-- tests/cmdline/commands/test_verdi.py | 7 +-- tests/conftest.py | 6 ++ tests/manage/configuration/test_options.py | 9 ++- tests/utils/configuration.py | 66 ---------------------- 7 files changed, 19 insertions(+), 98 deletions(-) diff --git a/tests/cmdline/commands/test_help.py b/tests/cmdline/commands/test_help.py index be2231c2f2..82310bbdb6 100644 --- a/tests/cmdline/commands/test_help.py +++ b/tests/cmdline/commands/test_help.py @@ -8,15 +8,14 @@ # For further information please visit http://www.aiida.net # ########################################################################### """Tests for `verdi help`.""" - from click.testing import CliRunner +import pytest from aiida.backends.testbase import AiidaTestCase from aiida.cmdline.commands import cmd_verdi -from tests.utils.configuration import with_temporary_config_instance - +@pytest.mark.usefixtures('config_with_profile') class TestVerdiHelpCommand(AiidaTestCase): """Tests for `verdi help`.""" @@ -24,7 +23,6 @@ def setUp(self): super().setUp() self.cli_runner = CliRunner() - @with_temporary_config_instance def test_without_arg(self): """ Ensure we get the same help for `verdi` (which gives the same as `verdi --help`) @@ -36,7 +34,6 @@ def test_without_arg(self): result_verdi = self.cli_runner.invoke(cmd_verdi.verdi, [], catch_exceptions=False) self.assertEqual(result_help.output, result_verdi.output) - @with_temporary_config_instance def test_cmd_help(self): """Ensure we get the same help for `verdi user --help` and `verdi help user`""" result_help = self.cli_runner.invoke(cmd_verdi.verdi, ['help', 'user'], catch_exceptions=False) diff --git a/tests/cmdline/commands/test_profile.py b/tests/cmdline/commands/test_profile.py index ddfbdd1183..7eb262eeb3 100644 --- a/tests/cmdline/commands/test_profile.py +++ b/tests/cmdline/commands/test_profile.py @@ -10,14 +10,16 @@ """Tests for `verdi profile`.""" from click.testing import CliRunner +import pytest from aiida.backends.testbase import AiidaPostgresTestCase from aiida.cmdline.commands import cmd_profile, cmd_verdi from aiida.manage import configuration -from tests.utils.configuration import create_mock_profile, with_temporary_config_instance +from tests.utils.configuration import create_mock_profile +@pytest.mark.usefixtures('config_with_profile') class TestVerdiProfileSetup(AiidaPostgresTestCase): """Tests for `verdi profile`.""" @@ -32,8 +34,7 @@ def mock_profiles(self, **kwargs): """Create mock profiles and a runner object to invoke the CLI commands. Note: this cannot be done in the `setUp` or `setUpClass` methods, because the temporary configuration instance - is not generated until the test function is entered, which calls the `with_temporary_config_instance` - decorator. + is not generated until the test function is entered, which calls the `config_with_profile` test fixture. """ self.config = configuration.get_config() self.profile_list = ['mock_profile1', 'mock_profile2', 'mock_profile3', 'mock_profile4'] @@ -44,7 +45,6 @@ def mock_profiles(self, **kwargs): self.config.set_default_profile(self.profile_list[0], overwrite=True).store() - @with_temporary_config_instance def test_help(self): """Tests help text for all `verdi profile` commands.""" self.mock_profiles() @@ -67,7 +67,6 @@ def test_help(self): self.assertClickSuccess(result) self.assertIn('Usage', result.output) - @with_temporary_config_instance def test_list(self): """Test the `verdi profile list` command.""" self.mock_profiles() @@ -78,7 +77,6 @@ def test_list(self): self.assertIn(f'* {self.profile_list[0]}', result.output) self.assertIn(self.profile_list[1], result.output) - @with_temporary_config_instance def test_setdefault(self): """Test the `verdi profile setdefault` command.""" self.mock_profiles() @@ -93,7 +91,6 @@ def test_setdefault(self): self.assertIn(f'* {self.profile_list[1]}', result.output) self.assertClickSuccess(result) - @with_temporary_config_instance def test_show(self): """Test the `verdi profile show` command.""" self.mock_profiles() @@ -109,7 +106,6 @@ def test_show(self): self.assertIn(key.lower(), result.output) self.assertIn(value, result.output) - @with_temporary_config_instance def test_show_with_profile_option(self): """Test the `verdi profile show` command in combination with `-p/--profile.""" self.mock_profiles() @@ -126,7 +122,6 @@ def test_show_with_profile_option(self): self.assertClickSuccess(result) self.assertTrue(profile_name_non_default not in result.output) - @with_temporary_config_instance def test_delete_partial(self): """Test the `verdi profile delete` command. @@ -142,7 +137,6 @@ def test_delete_partial(self): self.assertClickSuccess(result) self.assertNotIn(self.profile_list[1], result.output) - @with_temporary_config_instance def test_delete(self): """Test for verdi profile delete command.""" from aiida.cmdline.commands.cmd_profile import profile_delete, profile_list diff --git a/tests/cmdline/commands/test_setup.py b/tests/cmdline/commands/test_setup.py index d48061e3ee..8515be996e 100644 --- a/tests/cmdline/commands/test_setup.py +++ b/tests/cmdline/commands/test_setup.py @@ -20,9 +20,8 @@ from aiida.manage import configuration from aiida.manage.external.postgres import Postgres -from tests.utils.configuration import with_temporary_config_instance - +@pytest.mark.usefixtures('config_with_profile') class TestVerdiSetup(AiidaPostgresTestCase): """Tests for `verdi setup` and `verdi quicksetup`.""" @@ -34,7 +33,6 @@ def setUp(self): self.backend = configuration.PROFILE.database_backend self.cli_runner = CliRunner() - @with_temporary_config_instance def test_help(self): """Check that the `--help` option is eager, is not overruled and will properly display the help message. @@ -44,7 +42,6 @@ def test_help(self): self.cli_runner.invoke(cmd_setup.setup, ['--help'], catch_exceptions=False) self.cli_runner.invoke(cmd_setup.quicksetup, ['--help'], catch_exceptions=False) - @with_temporary_config_instance def test_quicksetup(self): """Test `verdi quicksetup`.""" configuration.reset_profile() @@ -79,7 +76,6 @@ def test_quicksetup(self): self.assertEqual(user.last_name, user_last_name) self.assertEqual(user.institution, user_institution) - @with_temporary_config_instance def test_quicksetup_from_config_file(self): """Test `verdi quicksetup` from configuration file.""" import tempfile @@ -99,7 +95,6 @@ def test_quicksetup_from_config_file(self): result = self.cli_runner.invoke(cmd_setup.quicksetup, ['--config', os.path.realpath(handle.name)]) self.assertClickResultNoException(result) - @with_temporary_config_instance def test_quicksetup_wrong_port(self): """Test `verdi quicksetup` exits if port is wrong.""" configuration.reset_profile() @@ -119,7 +114,6 @@ def test_quicksetup_wrong_port(self): result = self.cli_runner.invoke(cmd_setup.quicksetup, options) self.assertIsNotNone(result.exception, ''.join(traceback.format_exception(*result.exc_info))) - @with_temporary_config_instance def test_setup(self): """Test `verdi setup` (non-interactive).""" postgres = Postgres(interactive=False, quiet=True, dbinfo=self.pg_test.dsn) diff --git a/tests/cmdline/commands/test_verdi.py b/tests/cmdline/commands/test_verdi.py index 0791150dca..ed3aa88204 100644 --- a/tests/cmdline/commands/test_verdi.py +++ b/tests/cmdline/commands/test_verdi.py @@ -9,14 +9,14 @@ ########################################################################### """Tests for `verdi`.""" from click.testing import CliRunner +import pytest from aiida import get_version from aiida.backends.testbase import AiidaTestCase from aiida.cmdline.commands import cmd_verdi -from tests.utils.configuration import with_temporary_config_instance - +@pytest.mark.usefixtures('config_with_profile') class TestVerdi(AiidaTestCase): """Tests for `verdi`.""" @@ -30,7 +30,6 @@ def test_verdi_version(self): self.assertIsNone(result.exception, result.output) self.assertIn(get_version(), result.output) - @with_temporary_config_instance def test_verdi_with_empty_profile_list(self): """Regression test for #2424: verify that verdi remains operable even if profile list is empty""" from aiida.manage.configuration import CONFIG @@ -40,7 +39,6 @@ def test_verdi_with_empty_profile_list(self): result = self.cli_runner.invoke(cmd_verdi.verdi, []) self.assertIsNone(result.exception, result.output) - @with_temporary_config_instance def test_invalid_cmd_matches(self): """Test that verdi with an invalid command will return matches if somewhat close""" result = self.cli_runner.invoke(cmd_verdi.verdi, ['usr']) @@ -49,7 +47,6 @@ def test_invalid_cmd_matches(self): self.assertIn('user', result.output) self.assertNotEqual(result.exit_code, 0) - @with_temporary_config_instance def test_invalid_cmd_no_matches(self): """Test that verdi with an invalid command with no matches returns an appropriate message""" result = self.cli_runner.invoke(cmd_verdi.verdi, ['foobar']) diff --git a/tests/conftest.py b/tests/conftest.py index 1a1c7e1f00..0b0e379c11 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -268,6 +268,12 @@ def _config_with_profile_factory(set_as_default=True, load=True, name='default', return _config_with_profile_factory +@pytest.fixture +def config_with_profile(config_with_profile_factory): + """Create a temporary configuration instance with one default, loaded profile.""" + yield config_with_profile_factory() + + @pytest.fixture def manager(aiida_profile): # pylint: disable=unused-argument """Get the ``Manager`` instance of the currently loaded profile.""" diff --git a/tests/manage/configuration/test_options.py b/tests/manage/configuration/test_options.py index bf55730f77..86deb45999 100644 --- a/tests/manage/configuration/test_options.py +++ b/tests/manage/configuration/test_options.py @@ -8,14 +8,13 @@ # For further information please visit http://www.aiida.net # ########################################################################### """Tests for the configuration options.""" +import pytest from aiida.backends.testbase import AiidaTestCase from aiida.common.exceptions import ConfigurationError from aiida.manage.configuration.options import get_option, get_option_names, parse_option, Option from aiida.manage.configuration import get_config, get_config_option, ConfigValidationError -from tests.utils.configuration import with_temporary_config_instance - class TestConfigurationOptions(AiidaTestCase): """Tests for the Options class.""" @@ -53,7 +52,7 @@ def test_options(self): option.valid_type # pylint: disable=pointless-statement option.default # pylint: disable=pointless-statement - @with_temporary_config_instance + @pytest.mark.usefixtures('config_with_profile') def test_get_config_option_default(self): """Tests that `get_option` return option default if not specified globally or for current profile.""" option_name = 'logging.aiida_loglevel' @@ -63,7 +62,7 @@ def test_get_config_option_default(self): option_value = get_config_option(option_name) self.assertEqual(option_value, option.default) - @with_temporary_config_instance + @pytest.mark.usefixtures('config_with_profile') def test_get_config_option_profile_specific(self): """Tests that `get_option` correctly gets a configuration option if specified for the current profile.""" config = get_config() @@ -77,7 +76,7 @@ def test_get_config_option_profile_specific(self): option_value = get_config_option(option_name) self.assertEqual(option_value, option_value_profile) - @with_temporary_config_instance + @pytest.mark.usefixtures('config_with_profile') def test_get_config_option_global(self): """Tests that `get_option` correctly agglomerates upwards and so retrieves globally set config options.""" config = get_config() diff --git a/tests/utils/configuration.py b/tests/utils/configuration.py index ae922cef12..e3767af946 100644 --- a/tests/utils/configuration.py +++ b/tests/utils/configuration.py @@ -43,72 +43,6 @@ def create_mock_profile(name, repository_dirpath=None, **kwargs): return Profile(name, profile_dictionary) -@contextlib.contextmanager -def temporary_config_instance(): - """Create a temporary AiiDA instance.""" - current_config = None - current_config_path = None - current_profile_name = None - temporary_config_directory = None - - from aiida.common.utils import Capturing - from aiida.manage import configuration - from aiida.manage.configuration import settings, load_profile, reset_profile - - try: - from aiida.manage.configuration.settings import create_instance_directories - - # Store the current configuration instance and config directory path - current_config = configuration.CONFIG - current_config_path = current_config.dirpath - current_profile_name = configuration.PROFILE.name - - reset_profile() - configuration.CONFIG = None - - # Create a temporary folder, set it as the current config directory path and reset the loaded configuration - profile_name = 'test_profile_1234' - temporary_config_directory = tempfile.mkdtemp() - settings.AIIDA_CONFIG_FOLDER = temporary_config_directory - - # Create the instance base directory structure, the config file and a dummy profile - create_instance_directories() - - # The constructor of `Config` called by `load_config` will print warning messages about migrating it - with Capturing(): - configuration.CONFIG = configuration.load_config(create=True) - - profile = create_mock_profile(name=profile_name, repository_dirpath=temporary_config_directory) - - # Add the created profile and set it as the default - configuration.CONFIG.add_profile(profile) - configuration.CONFIG.set_default_profile(profile_name, overwrite=True) - configuration.CONFIG.store() - load_profile() - - yield configuration.CONFIG - finally: - # Reset the config folder path and the config instance - reset_profile() - settings.AIIDA_CONFIG_FOLDER = current_config_path - configuration.CONFIG = current_config - load_profile(current_profile_name) - - # Destroy the temporary instance directory - if temporary_config_directory and os.path.isdir(temporary_config_directory): - shutil.rmtree(temporary_config_directory) - - -def with_temporary_config_instance(function): - """Create a temporary AiiDA instance for the duration of the wrapped function.""" - - def decorated_function(*args, **kwargs): - with temporary_config_instance(): - function(*args, **kwargs) - - return decorated_function - - @contextlib.contextmanager def temporary_directory(): """Create a temporary directory."""