Skip to content

Commit ecc8b0d

Browse files
committed
Testsuite works with local infrastructure
1 parent 64ea0b0 commit ecc8b0d

File tree

11 files changed

+161
-148
lines changed

11 files changed

+161
-148
lines changed

.idea/runConfigurations/test__resources_.xml

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/runConfigurations/tests.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/runConfigurations/tests__no_infrastructure_.xml

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mrmat_python_api_flask/apis/resource/v1/api.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,18 @@ def _extract_identity() -> Tuple:
4444
@bp.route('/', methods=['GET'])
4545
@oidc.accept_token(require_token=True, scopes_required=['mpaf-read'])
4646
def get_all():
47-
identity = _extract_identity()
48-
logger.info(f'Called by {identity[1]} ({identity[0]}')
47+
(client_id, name) = _extract_identity()
48+
logger.info(f'Called by {client_id} for {name}')
4949
a = Resource.query.all()
5050
return {'resources': resources_schema.dump(a)}, 200
5151

5252

5353
@bp.route('/<i>', methods=['GET'])
5454
@oidc.accept_token(require_token=True, scopes_required=['mpaf-read'])
5555
def get_one(i: int):
56-
identity = _extract_identity()
57-
logger.info(f'Called by {identity[1]} ({identity[0]}')
58-
resource = Resource.query.filter(Resource.id == i).first_or_404()
56+
(client_id, name) = _extract_identity()
57+
logger.info(f'Called by {client_id} for {name}')
58+
resource = Resource.query.filter(Resource.id == i).one_or_none()
5959
if resource is None:
6060
return {'status': 404, 'message': f'Unable to find entry with identifier {i} in database'}, 404
6161
return resource_schema.dump(resource), 200
@@ -65,7 +65,7 @@ def get_one(i: int):
6565
@oidc.accept_token(require_token=True, scopes_required=['mpaf-write'])
6666
def create():
6767
(client_id, name) = _extract_identity()
68-
logger.info(f'Called by {name} ({client_id}')
68+
logger.info(f'Called by {client_id} for {name}')
6969
try:
7070
json_body = request.get_json()
7171
if not json_body:
@@ -102,7 +102,7 @@ def create():
102102
@oidc.accept_token(require_token=True, scopes_required=['mpaf-write'])
103103
def modify(i: int):
104104
(client_id, name) = _extract_identity()
105-
logger.info(f'Called by {name} ({client_id}')
105+
logger.info(f'Called by {client_id} for {name}')
106106
body = resource_schema.load(request.get_json())
107107

108108
resource = Resource.query.filter(Resource.id == i).one_or_none()
@@ -121,11 +121,11 @@ def modify(i: int):
121121
@oidc.accept_token(require_token=True, scopes_required=['mpaf-write'])
122122
def remove(i: int):
123123
(client_id, name) = _extract_identity()
124-
logger.info(f'Called by {name} ({client_id}')
124+
logger.info(f'Called by {client_id} for {name}')
125125

126126
resource = Resource.query.filter(Resource.id == i).one_or_none()
127127
if resource is None:
128-
return {'status': 410, 'message': 'Unable to find requested resource'}, 410
128+
return {'status': 410, 'message': 'The requested resource is permanently deleted'}, 410
129129
if resource.owner.client_id != client_id:
130130
return {'status': 401, 'message': 'You do not own this resource'}, 401
131131

tests/conftest.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
# SOFTWARE.
22-
import abc
22+
2323
import os
2424
import logging
2525
import json
@@ -36,7 +36,7 @@
3636
import psycopg2.extensions
3737

3838
from flask_migrate import upgrade
39-
from keycloak import KeycloakOpenID, KeycloakAdmin
39+
from keycloak.keycloak_admin import KeycloakOpenID, KeycloakAdmin
4040
from keycloak.exceptions import KeycloakOperationError
4141

4242
from mrmat_python_api_flask import create_app, db
@@ -140,7 +140,7 @@ def app_dsn(self,
140140
self._pg_admin.commit()
141141
cur.close()
142142

143-
dsn_info = psycopg2.extensions.ConnectionInfo = psycopg2.extensions.parse_dsn(self._ti_config['keycloak'].
143+
dsn_info = psycopg2.extensions.ConnectionInfo = psycopg2.extensions.parse_dsn(self._ti_config['pg'].
144144
get('admin_dsn'))
145145
app_dsn = f"postgresql://{role}:{password}@{dsn_info['host']}:{dsn_info['port']}/{dsn_info['dbname']}"
146146
yield app_dsn
@@ -171,12 +171,13 @@ def app_auth(self,
171171
if scopes is None:
172172
scopes = []
173173
for scope in scopes:
174-
self._keycloak_admin.create_client_scope({
175-
'id': scope,
176-
'name': scope,
177-
'description': f'Test {scope}',
178-
'protocol': 'openid-connect'
179-
}, skip_exists=True)
174+
if not self._keycloak_admin.get_client_scope(scope):
175+
self._keycloak_admin.create_client_scope({
176+
'id': scope,
177+
'name': scope,
178+
'description': f'Test {scope}',
179+
'protocol': 'openid-connect'
180+
})
180181
if not self._keycloak_admin.get_client_id(client_id):
181182
self._keycloak_admin.create_client({
182183
'id': client_id,
@@ -255,8 +256,9 @@ def app(self,
255256
yield self._app
256257

257258
@contextlib.contextmanager
258-
def app_client(self):
259-
yield self._app.test_client()
259+
def app_client(self, app_dir):
260+
with self.app(app_dir) as app:
261+
yield app.test_client()
260262

261263
@contextlib.contextmanager
262264
def user_token(self,
@@ -282,9 +284,8 @@ def user_token(self,
282284
client_secret_key=self._auth_info['ti_secret'],
283285
realm_name='master',
284286
verify=True)
285-
token = keycloak.token(self._auth_info['user_id'],
286-
self._auth_info['user_password'],
287-
scope=scopes)
287+
token = keycloak.token(user_id, user_password, scope=scopes)
288+
token['user_id'] = user_id
288289
yield token
289290
finally:
290291
if drop_finally:
@@ -311,5 +312,5 @@ def local_test_infrastructure():
311312
312313
"""
313314
if 'TI_CONFIG' not in os.environ:
314-
raise TIException(skip=True, msg='There is no TI_CONFIG environment variable to configure the environment')
315+
pytest.skip('There is TI_CONFIG environment variable configuring local infrastructure to test with')
315316
yield LocalTestInfrastructure(ti_config_path=pathlib.Path(os.path.expanduser(os.getenv('TI_CONFIG'))))

tests/resource_api_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def __init__(self, client: FlaskClient, token: Optional[Dict]):
3535
self.client = client
3636
self.token = token
3737
if token is not None:
38-
self._headers = {'Authorization': f'Bearer {token["access_token"]}'}
38+
self._headers = {'Authorization': f'Bearer {token}'}
3939

4040
def get_all(self) -> Tuple:
4141
resp: Response = self.client.get('/api/resource/v1/', headers=self._headers)

tests/test_greeting_v1.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,14 @@
2323
import pytest
2424

2525
from flask import Response
26-
from flask.testing import FlaskClient
2726

28-
@pytest.mark.skip
29-
def test_greeting_v1(client: FlaskClient):
30-
rv: Response = client.get('/api/greeting/v1/')
31-
json_body = rv.get_json()
32-
assert 'message' in json_body
33-
assert json_body['message'] == 'Hello World'
27+
28+
@pytest.mark.usefixtures('no_test_infrastructure')
29+
class TestWithoutInfrastructure:
30+
31+
def test_greeting_v1(self, no_test_infrastructure):
32+
with no_test_infrastructure.app_client() as client:
33+
rv: Response = client.get('/api/greeting/v1/')
34+
json_body = rv.get_json()
35+
assert 'message' in json_body
36+
assert json_body['message'] == 'Hello World'

tests/test_greeting_v2.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@
2323
import pytest
2424

2525
from flask import Response
26-
from flask.testing import FlaskClient
2726

2827

29-
@pytest.mark.skip
30-
def test_greeting_v2(client: FlaskClient):
31-
rv: Response = client.get('/api/greeting/v2/?name=MrMat')
32-
json_body = rv.get_json()
33-
assert 'message' in json_body
34-
assert json_body['message'] == 'Hello MrMat'
28+
@pytest.mark.usefixtures('no_test_infrastructure')
29+
class TestWithoutInfrastructure:
30+
31+
def test_greeting_v2(self, no_test_infrastructure):
32+
with no_test_infrastructure.app_client() as client:
33+
rv: Response = client.get('/api/greeting/v2/?name=MrMat')
34+
json_body = rv.get_json()
35+
assert 'message' in json_body
36+
assert json_body['message'] == 'Hello MrMat'

tests/test_greeting_v3.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,18 @@
2121
# SOFTWARE.
2222

2323
import pytest
24-
25-
from typing import Optional, Dict
2624
from flask import Response
27-
from flask.testing import FlaskClient
2825

2926

30-
@pytest.mark.skip
31-
def test_greeting_v3(client: FlaskClient, test_config: Dict, oidc_token_read: Optional[Dict]):
32-
if oidc_token_read is None:
33-
pytest.skip('Skip test because there is no OIDC client configuration')
34-
rv: Response = client.get('/api/greeting/v3/',
35-
headers={'Authorization': f'Bearer {oidc_token_read["access_token"]}'})
36-
assert rv.status_code == 200
37-
json_body = rv.get_json()
38-
assert 'message' in json_body
39-
assert json_body['message'] == f'Hello {test_config["client"]["preferred_name"]}'
27+
@pytest.mark.usefixtures('local_test_infrastructure')
28+
class TestWithLocalInfrastructure:
29+
30+
def test_greeting_v3(self, tmpdir, local_test_infrastructure):
31+
with local_test_infrastructure.app_client(tmpdir) as client:
32+
with local_test_infrastructure.user_token() as user_token:
33+
rv: Response = client.get('/api/greeting/v3/',
34+
headers={'Authorization': f'Bearer {user_token["access_token"]}'})
35+
assert rv.status_code == 200
36+
json_body = rv.get_json()
37+
assert 'message' in json_body
38+
assert json_body['message'] == f'Hello {user_token["user_id"]}'

tests/test_healthz.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,14 @@
2323
import pytest
2424

2525
from flask import Response
26-
from flask.testing import FlaskClient
2726

2827

2928
@pytest.mark.usefixtures('no_test_infrastructure')
30-
class TestNoInfrastructure:
29+
class TestWithoutInfrastructure:
3130

3231
def test_healthz(self, no_test_infrastructure):
3332
with no_test_infrastructure.app_client() as client:
3433
rv: Response = client.get('/healthz/')
3534
json_body = rv.get_json()
3635
assert 'status' in json_body
3736
assert json_body['status'] == 'OK'
38-
39-
40-
@pytest.mark.skip
41-
def test_healthz(client: FlaskClient):
42-
rv: Response = client.get('/healthz/')
43-
json_body = rv.get_json()
44-
assert 'status' in json_body
45-
assert json_body['status'] == 'OK'

0 commit comments

Comments
 (0)