From 048d06de3738504634f282e1906d13a99f88c873 Mon Sep 17 00:00:00 2001 From: Maxime Alves LIRMM Date: Wed, 5 Aug 2020 11:10:14 +0200 Subject: [PATCH] [tests] moved cli tests to one file with incremental tests (exits if one fails) --- tests/cli/test_init_project.py | 56 ------------- tests/conftest.py | 53 +++++++++++++ tests/test_cli.py | 138 +++++++++++++++++++++++++++------ tests/test_cli_init_project.py | 92 ---------------------- 4 files changed, 168 insertions(+), 171 deletions(-) delete mode 100644 tests/cli/test_init_project.py create mode 100644 tests/conftest.py delete mode 100644 tests/test_cli_init_project.py diff --git a/tests/cli/test_init_project.py b/tests/cli/test_init_project.py deleted file mode 100644 index ee10e2c..0000000 --- a/tests/cli/test_init_project.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 -import os -import subprocess - -import pytest -from click.testing import CliRunner - -from halfapi import __version__ -from halfapi.cli import cli -from configparser import ConfigParser - -projname = os.environ.get('PROJ','tmp_api') - -@pytest.fixture -def dropdb(): - p = subprocess.Popen(['dropdb', f'halfapi_{projname}']) - p.wait() - yield - - p = subprocess.Popen(['dropdb', f'halfapi_{projname}']) - p.wait() - -def test_init_project(dropdb): - runner = CliRunner() - cp = ConfigParser() - with runner.isolated_filesystem(): - env = { - 'HALFORM_CONF_DIR': os.environ.get('HALFORM_CONF_DIR', os.getcwd()), - 'HALFAPI_CONF_DIR': os.environ.get('HALFAPI_CONF_DIR', os.getcwd()), - } - - res = runner.invoke(cli, ['init-project', projname], env=env) - try: - assert os.path.isdir(projname) - assert os.path.isdir(os.path.join(projname, '.halfapi')) - - - # .halfapi/config check - assert os.path.isfile(os.path.join(projname, '.halfapi', 'config')) - cp.read(os.path.join(projname, '.halfapi', 'config')) - assert cp.has_section('project') - assert cp.has_option('project', 'name') - assert cp.get('project', 'name') == projname - assert cp.get('project', 'halfapi_version') == __version__ - - # .halfapi/domains check - assert os.path.isfile(os.path.join(projname, '.halfapi', 'domains')) - cp.read(os.path.join(projname, '.halfapi', 'domains')) - assert cp.has_section('domains') - except AssertionError: - subprocess.run(['tree', '-a', os.getcwd()]) - - assert res.exit_code == 0 - assert res.exception is None - - diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..3cb2e0c --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,53 @@ +# content of conftest.py + +from typing import Dict, Tuple +import pytest + +# store history of failures per test class name and per index in parametrize (if +# parametrize used) +_test_failed_incremental: Dict[str, Dict[Tuple[int, ...], str]] = {} + + +def pytest_runtest_makereport(item, call): + if "incremental" in item.keywords: + # incremental marker is used + if call.excinfo is not None: + # the test has failed + # retrieve the class name of the test + cls_name = str(item.cls) + # retrieve the index of the test (if parametrize is used in + # combination with incremental) + parametrize_index = ( + tuple(item.callspec.indices.values()) + if hasattr(item, "callspec") + else () + ) + # retrieve the name of the test function + test_name = item.originalname or item.name + # store in _test_failed_incremental the original name of the failed + # test + _test_failed_incremental.setdefault(cls_name, {}).setdefault( + parametrize_index, test_name + ) + + +def pytest_runtest_setup(item): + if "incremental" in item.keywords: + # retrieve the class name of the test + cls_name = str(item.cls) + # check if a previous test has failed for this class + if cls_name in _test_failed_incremental: + # retrieve the index of the test (if parametrize is used in + # combination with incremental) + parametrize_index = ( + tuple(item.callspec.indices.values()) + if hasattr(item, "callspec") + else () + ) + # retrieve the name of the first test function to fail for this + # class name and index + test_name = _test_failed_incremental[cls_name].get(parametrize_index, None) + # if name found, test has failed for the combination of class name & + # test name + if test_name is not None: + pytest.xfail("previous test failed ({})".format(test_name)) diff --git a/tests/test_cli.py b/tests/test_cli.py index b5e31e1..fe25c8d 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,42 +1,134 @@ #!/usr/bin/env python3 import os +import subprocess import pytest from click.testing import CliRunner +from configparser import ConfigParser +from halfapi import __version__ from halfapi.cli import cli +PROJNAME = os.environ.get('PROJ','tmp_api') + @pytest.fixture def runner(): return CliRunner() -def test_cli(runner): - # Wrong command - with runner.isolated_filesystem(): - r = runner.invoke(cli, ['foobar']) + +@pytest.fixture +def dropdb(): + p = subprocess.Popen(['dropdb', f'halfapi_{PROJNAME}']) + p.wait() + yield + + p = subprocess.Popen(['dropdb', f'halfapi_{PROJNAME}']) + p.wait() + + +@pytest.mark.incremental +class TestCli(): + def test_options(self, runner, dropdb): + # Wrong command + with runner.isolated_filesystem(): + r = runner.invoke(cli, ['foobar']) + assert r.exit_code == 2 + + # Test existing commands + with runner.isolated_filesystem(): + r = runner.invoke(cli, ['--help']) + assert r.exit_code == 0 + + with runner.isolated_filesystem(): + r = runner.invoke(cli, ['--version']) + assert r.exit_code == 0 + + with runner.isolated_filesystem(): + r = runner.invoke(cli, ['init-project', '--help']) + assert r.exit_code == 0 + + with runner.isolated_filesystem(): + r = runner.invoke(cli, ['run', '--help']) + assert r.exit_code == 0 + + with runner.isolated_filesystem(): + r = runner.invoke(cli, ['domain', '--help']) + assert r.exit_code == 0 + + + def test_init_project_fail(self, runner, dropdb): + # Missing argument (project) + testproject = 'testproject' + r = runner.invoke(cli, ['init-project']) assert r.exit_code == 2 - # Test existing commands - with runner.isolated_filesystem(): - r = runner.invoke(cli, ['--help']) - assert r.exit_code == 0 + with runner.isolated_filesystem(): + # Fail : Wrong project name + r = runner.invoke(cli, ['init-project', 'test*-project']) + assert r.exit_code == 1 - with runner.isolated_filesystem(): - r = runner.invoke(cli, ['--version']) - assert r.exit_code == 0 + with runner.isolated_filesystem(): + # Fail : Already existing folder + os.mkdir(testproject) + r = runner.invoke(cli, ['init-project', testproject]) + assert r.exit_code == 1 - with runner.isolated_filesystem(): - r = runner.invoke(cli, ['init-project', '--help']) - assert r.exit_code == 0 + with runner.isolated_filesystem(): + # Fail : Already existing nod + os.mknod(testproject) + r = runner.invoke(cli, ['init-project', testproject]) + assert r.exit_code == 1 - with runner.isolated_filesystem(): - r = runner.invoke(cli, ['run', '--help']) - assert r.exit_code == 0 + def test_init_project(self, runner, dropdb): + cp = ConfigParser() + with runner.isolated_filesystem(): + env = { + 'HALFORM_CONF_DIR': os.environ.get('HALFORM_CONF_DIR', os.getcwd()), + 'HALFAPI_CONF_DIR': os.environ.get('HALFAPI_CONF_DIR', os.getcwd()), + } - with runner.isolated_filesystem(): - r = runner.invoke(cli, ['domain', '--help']) - assert r.exit_code == 0 + res = runner.invoke(cli, ['init-project', PROJNAME], env=env) + try: + assert os.path.isdir(PROJNAME) + assert os.path.isdir(os.path.join(PROJNAME, '.halfapi')) - with runner.isolated_filesystem(): - r = runner.invoke(cli, ['routes', '--help']) - assert r.exit_code == 0 + + # .halfapi/config check + assert os.path.isfile(os.path.join(PROJNAME, '.halfapi', 'config')) + cp.read(os.path.join(PROJNAME, '.halfapi', 'config')) + assert cp.has_section('project') + assert cp.has_option('project', 'name') + assert cp.get('project', 'name') == PROJNAME + assert cp.get('project', 'halfapi_version') == __version__ + + # .halfapi/domains check + assert os.path.isfile(os.path.join(PROJNAME, '.halfapi', 'domains')) + cp.read(os.path.join(PROJNAME, '.halfapi', 'domains')) + assert cp.has_section('domains') + except AssertionError: + subprocess.run(['tree', '-a', os.getcwd()]) + + assert res.exit_code == 0 + assert res.exception is None + + + def test_domain_commands(self, runner, dropdb): + with runner.isolated_filesystem(): + res = runner.invoke(cli, ['domain', 'foobar']) + assert res.exit_code == 2 + + with runner.isolated_filesystem(): + res = runner.invoke(cli, ['domain', 'create', '--help']) + assert r.exit_code == 0 + + with runner.isolated_filesystem(): + res = runner.invoke(cli, ['domain', 'read', '--help']) + assert r.exit_code == 0 + + with runner.isolated_filesystem(): + res = runner.invoke(cli, ['domain', 'update', '--help']) + assert r.exit_code == 0 + + with runner.isolated_filesystem(): + res = runner.invoke(cli, ['domain', 'delete', '--help']) + assert r.exit_code == 0 diff --git a/tests/test_cli_init_project.py b/tests/test_cli_init_project.py deleted file mode 100644 index 73eecd9..0000000 --- a/tests/test_cli_init_project.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python3 -import os - -import pytest -from click.testing import CliRunner - -from halfapi import __version__ -from halfapi.cli import cli -from configparser import ConfigParser - -@pytest.fixture -def runner(): - return CliRunner() - -@pytest.mark.skip -def test_init_project(runner): - # Missing argument (project) - testproject = 'testproject' - r = runner.invoke(cli, ['init-project']) - assert r.exit_code == 2 - - with runner.isolated_filesystem(): - # Fail : Wrong project name - r = runner.invoke(cli, ['init-project', 'test*-project']) - assert r.exit_code == 1 - - with runner.isolated_filesystem(): - # Fail : Already existing folder - os.mkdir(testproject) - r = runner.invoke(cli, ['init-project', testproject]) - assert r.exit_code == 1 - - with runner.isolated_filesystem(): - # Fail : Already existing nod - os.mknod(testproject) - r = runner.invoke(cli, ['init-project', testproject]) - assert r.exit_code == 1 - - - with runner.isolated_filesystem(): - # Fail : No rights in /etc - r = runner.invoke(cli, ['init-project', testproject], env={ - 'HALFORM_CONF_DIR':'/etc/half_orm' - }) - assert r.exit_code == 1 - assert type(r.exception) is PermissionError - -testproject = 'testproject' - -import subprocess -@pytest.fixture -def dropdb(): - subprocess.run(['/usr/bin/dropdb', f'halfapi_{testproject}']) - - yield - - return subprocess.run(['/usr/bin/dropdb', f'halfapi_{testproject}']) - -def test_init_project_success(runner, dropdb): - with runner.isolated_filesystem(): - # Success : New repo - r = runner.invoke(cli, ['init-project', testproject]) - assert r.exit_code == 0 - assert os.path.isdir(testproject) - assert os.path.isdir(f'{testproject}/.git') - assert os.path.isdir(f'{testproject}/.halfapi') - domains_file = 'testproject/.halfapi/domains' - assert os.path.isfile(domains_file) - conf_file = 'testproject/.halfapi/config' - assert os.path.isfile(conf_file) - config = ConfigParser() - config.read([conf_file]) - assert config.has_section('project') - assert config.has_option('project', 'name') - assert config.get('project', 'name') == testproject - assert config.get('project', 'halfapi_version') == __version__ - - -@pytest.mark.skip -def test_init_project_clone_success(runner): - with runner.isolated_filesystem(): - # Success : Cloned repo - import pygit2 - pygit2.init_repository('testproject.git', bare=True) - assert os.path.isdir('testproject.git') - - r = runner.invoke(cli, [ - 'init-project', testproject, '--repo', - f'./{testproject}.git']) - assert r.exit_code == 0 - assert os.path.isdir(testproject) - assert os.path.isdir('testproject/.git')