Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🧪 TESTS: add config_with_profile fixture #4764

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions tests/cmdline/commands/test_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,21 @@
# 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`."""

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`)
Expand All @@ -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)
Expand Down
14 changes: 4 additions & 10 deletions tests/cmdline/commands/test_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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`."""

Expand All @@ -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']
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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()
Expand All @@ -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.

Expand All @@ -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
Expand Down
8 changes: 1 addition & 7 deletions tests/cmdline/commands/test_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -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`."""

Expand All @@ -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.

Expand All @@ -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()
Expand Down Expand Up @@ -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
Expand All @@ -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()
Expand All @@ -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)
Expand Down
7 changes: 2 additions & 5 deletions tests/cmdline/commands/test_verdi.py
Original file line number Diff line number Diff line change
Expand Up @@ -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`."""

Expand All @@ -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
Expand All @@ -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'])
Expand All @@ -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'])
Expand Down
6 changes: 6 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down
9 changes: 4 additions & 5 deletions tests/manage/configuration/test_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down Expand Up @@ -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'
Expand All @@ -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()
Expand All @@ -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()
Expand Down
66 changes: 0 additions & 66 deletions tests/utils/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down