[tests][OK] Using a dummy_domain, adding it and listing it's routes

This commit is contained in:
Maxime Alves LIRMM 2020-10-07 09:52:23 +02:00
parent f5ebabbcd4
commit 40547ddf30
9 changed files with 136 additions and 50 deletions

View File

@ -1,43 +1,73 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import logging
import functools
import re import re
import os import os
import subprocess import subprocess
import importlib import importlib
import tempfile import tempfile
import click
from unittest.mock import patch from unittest.mock import patch
from typing import Dict, Tuple from typing import Dict, Tuple
import pytest import pytest
from uuid import uuid1 from uuid import uuid1
from click.testing import CliRunner from click.testing import CliRunner
from halfapi import __version__ from halfapi import __version__
from halfapi.cli import cli from halfapi.cli.cli import cli
from halfapi.cli.init import format_halfapi_etc from halfapi.cli.init import init, format_halfapi_etc
Cli = cli.cli from halfapi.cli.domain import domain, create_domain
logger = logging.getLogger('halfapitest')
PROJNAME = os.environ.get('PROJ','tmp_api') PROJNAME = os.environ.get('PROJ','tmp_api')
@pytest.fixture @pytest.fixture
def runner(): def runner():
return CliRunner() return CliRunner()
def halfapicli(runner):
return lambda *args: runner.invoke(Cli, args) @pytest.fixture
def cli_runner():
"""Yield a click.testing.CliRunner to invoke the CLI."""
class_ = click.testing.CliRunner
def invoke_wrapper(f):
"""Augment CliRunner.invoke to emit its output to stdout.
This enables pytest to show the output in its logs on test
failures.
"""
@functools.wraps(f)
def wrapper(*args, **kwargs):
echo = kwargs.pop('echo', False)
result = f(*args, **kwargs)
if echo is True:
sys.stdout.write(result.output)
return result
return wrapper
class_.invoke = invoke_wrapper(class_.invoke)
cli_runner_ = class_()
yield cli_runner_
@pytest.fixture @pytest.fixture
def dropdb(): def halfapicli(cli_runner):
p = subprocess.Popen(['dropdb', f'halfapi_{PROJNAME}']) def caller(*args):
p.wait() return cli_runner.invoke(cli, ' '.join(args))
yield
p = subprocess.Popen(['dropdb', f'halfapi_{PROJNAME}']) yield caller
p.wait()
@pytest.fixture @pytest.fixture
def createdb(): def halfapi_conf_dir():
p = subprocess.Popen(['createdb', f'halfapi_{PROJNAME}']) return confdir('HALFAPI_CONF_DIR')
p.wait()
return
def confdir(dirname): def confdir(dirname):
d = os.environ.get(dirname) d = os.environ.get(dirname)
@ -52,10 +82,6 @@ def confdir(dirname):
def halform_conf_dir(): def halform_conf_dir():
return confdir('HALFORM_CONF_DIR') return confdir('HALFORM_CONF_DIR')
@pytest.fixture
def halfapi_conf_dir():
return confdir('HALFAPI_CONF_DIR')
# store history of failures per test class name and per index in parametrize (if # store history of failures per test class name and per index in parametrize (if
# parametrize used) # parametrize used)
_test_failed_incremental: Dict[str, Dict[Tuple[int, ...], str]] = {} _test_failed_incremental: Dict[str, Dict[Tuple[int, ...], str]] = {}
@ -106,28 +132,32 @@ def pytest_runtest_setup(item):
pytest.xfail("previous test failed ({})".format(test_name)) pytest.xfail("previous test failed ({})".format(test_name))
@pytest.fixture @pytest.fixture
def project_runner(runner, halfapi_conf_dir): def project_runner(runner, halfapicli, halfapi_conf_dir):
global Cli
env = {
'HALFAPI_CONF_DIR': halfapi_conf_dir
}
with runner.isolated_filesystem(): with runner.isolated_filesystem():
res = runner.invoke(Cli, ['init', PROJNAME], res = halfapicli('init', PROJNAME)
env=env,
catch_exceptions=True) try:
assert res.exit_code == 0 os.chdir(PROJNAME)
except FileNotFoundError as exc:
subprocess.call('tree')
raise exc
os.chdir(PROJNAME)
secret = tempfile.mkstemp() secret = tempfile.mkstemp()
SECRET_PATH = secret[1] SECRET_PATH = secret[1]
with open(SECRET_PATH, 'w') as f: with open(SECRET_PATH, 'w') as f:
f.write(str(uuid1())) f.write(str(uuid1()))
with open(os.path.join(halfapi_conf_dir, PROJNAME), 'w') as f: with open(os.path.join(halfapi_conf_dir, PROJNAME), 'w') as halfapi_etc:
PROJ_CONFIG = re.sub('secret = .*', f'secret = {SECRET_PATH}', PROJ_CONFIG = re.sub('secret = .*', f'secret = {SECRET_PATH}',
format_halfapi_etc(PROJNAME, os.getcwd())) format_halfapi_etc(PROJNAME, os.getcwd()))
f.write(PROJ_CONFIG) halfapi_etc.write(PROJ_CONFIG)
importlib.reload(cli)
Cli = cli.cli ###
yield halfapicli(runner) # add dummy domain
###
create_domain('dummy_domain', '.dummy_domain')
###
yield halfapicli

View File

View File

@ -0,0 +1 @@
public = lambda *args: True

View File

@ -1,3 +1,5 @@
from starlette.responses import PlainTextResponse
ROUTES={ ROUTES={
'': { '': {
'GET': [{'acl':None, 'in':None}] 'GET': [{'acl':None, 'in':None}]
@ -10,3 +12,11 @@ ROUTES={
} }
} }
async def get(request, *args, **kwargs):
"""
responses:
200:
description: dummy abc.alphabet route
"""
return PlainTextResponse('True')

View File

@ -18,7 +18,7 @@ PROJNAME = os.environ.get('PROJ','tmp_api')
@pytest.mark.incremental @pytest.mark.incremental
class TestCli(): class TestCli():
def test_options(self, runner, dropdb, createdb): def test_options(self, runner):
# Wrong command # Wrong command
with runner.isolated_filesystem(): with runner.isolated_filesystem():
r = runner.invoke(Cli, ['foobar']) r = runner.invoke(Cli, ['foobar'])
@ -38,7 +38,7 @@ class TestCli():
assert r.exit_code == 0 assert r.exit_code == 0
def test_init_project_fail(self, runner, dropdb): def test_init_project_fail(self, runner):
# Missing argument (project) # Missing argument (project)
testproject = 'testproject' testproject = 'testproject'
r = runner.invoke(Cli, ['init']) r = runner.invoke(Cli, ['init'])

View File

@ -15,15 +15,21 @@ PROJNAME = os.environ.get('PROJ','tmp_api')
@pytest.mark.incremental @pytest.mark.incremental
class TestCliProj(): class TestCliProj():
def test_cmds(self, project_runner): def test_cmds(self, project_runner):
print(os.getcwd())
assert project_runner('--help').exit_code == 0 assert project_runner('--help').exit_code == 0
#assert project_runner('run', '--help').exit_code == 0 #assert project_runner('run', '--help').exit_code == 0
#assert project_runner('domain', '--help').exit_code == 0 #assert project_runner('domain', '--help').exit_code == 0
def test_domain_commands(self, project_runner):
r = project_runner('domain')
assert r.exit_code == 0
@pytest.mark.skip
def test_config_commands(self, project_runner): def test_config_commands(self, project_runner):
assert project_runner('config') == 0 try:
r = project_runner('config')
assert r.exit_code == 0
except AssertionError as exc:
subprocess.call(['tree', '-a'])
raise exc
def test_domain_commands(self, subproc):
assert project_runner('domain') == 0

View File

@ -1,12 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from starlette.routing import Route import importlib
from halfapi.lib.domain import VERBS, gen_router_routes from halfapi.lib.domain import VERBS, gen_domain_routes, gen_router_routes
from halfapi.lib.routes import gen_starlette_routes
def test_gen_router_routes(): def test_gen_router_routes():
from .dummy_domain import routers from .dummy_domain import routers
for path, d_route in gen_router_routes(routers): for path, d_route in gen_router_routes(routers, ['dummy_domain']):
assert isinstance(path, str) assert isinstance(path, str)
for verb in VERBS: for verb in VERBS:
if verb not in d_route.keys(): if verb not in d_route.keys():
@ -15,12 +14,12 @@ def test_gen_router_routes():
print(f'[{verb}] {path} {route["fct"]}') print(f'[{verb}] {path} {route["fct"]}')
assert len(route['params']) > 0 assert len(route['params']) > 0
assert hasattr(route['fct'], '__call__') assert hasattr(route['fct'], '__call__')
if hasattr('fqtn', route): if 'fqtn' in route:
assert isinstance(route['fqtn'], str) assert isinstance(route['fqtn'], str)
def test_gen_starlette_routes(): def test_gen_domain_routes():
from . import dummy_domain from . import dummy_domain
for route in gen_starlette_routes(dummy_domain): for route in gen_domain_routes(
assert isinstance(route, Route) 'dummy_domain', dummy_domain):
assert isinstance(route, dict)

10
tests/test_lib_routes.py Normal file
View File

@ -0,0 +1,10 @@
from starlette.routing import Route
from halfapi.lib.routes import gen_starlette_routes
def test_gen_starlette_routes():
from . import dummy_domain
for path, route in gen_starlette_routes({
'dummy_domain': dummy_domain }):
assert isinstance(path, str)
assert isinstance(route, Route)

30
tests/test_lib_schemas.py Normal file
View File

@ -0,0 +1,30 @@
import subprocess
from pprint import pprint
from starlette.testclient import TestClient
from starlette.authentication import (
AuthenticationBackend, AuthenticationError, BaseUser, AuthCredentials,
UnauthenticatedUser)
from halfapi.app import application
from halfapi.lib.schemas import schema_dict_dom
def test_schemas_dict_dom():
from . import dummy_domain
schema = schema_dict_dom({
'dummy_domain':dummy_domain})
assert isinstance(schema, dict)
def test_get_api_routes(project_runner):
c = TestClient(application)
r = c.get('/')
d_r = r.json()
try:
assert isinstance(d_r, dict)
assert 'paths' in d_r
assert '/' in d_r['paths']
assert '/dummy_domain/abc/alphabet' in d_r['paths']
except AssertionError as exc:
pprint(d_r)
raise exc