From 9424efdd36e5001d47a246a5960f90f96acd62a5 Mon Sep 17 00:00:00 2001 From: Alexander Date: Thu, 4 Nov 2021 18:52:54 -0500 Subject: [PATCH 1/2] refactor: TT-357 refactor module database and imports --- .../azure/activity_azure_endpoints_test.py | 49 +++--- .../daos/activities_sql_dao_test.py | 147 ++++++++---------- .../_activities/_delete_activity.py | 16 +- .../_activities/_get_activities.py | 18 +-- .../_activities/_update_activity.py | 21 +-- .../_persistence_contracts/_activities_dao.py | 6 +- V2/time_entries/_infrastructure/__init__.py | 1 + .../_data_persistence/__init__.py | 2 +- .../_data_persistence/_activities_sql_dao.py | 27 +++- .../_data_persistence/_config.py | 12 -- .../_infrastructure/_data_persistence/_db.py | 17 +- 11 files changed, 149 insertions(+), 167 deletions(-) diff --git a/V2/tests/api/azure/activity_azure_endpoints_test.py b/V2/tests/api/azure/activity_azure_endpoints_test.py index e983fcaa..1cbafb17 100644 --- a/V2/tests/api/azure/activity_azure_endpoints_test.py +++ b/V2/tests/api/azure/activity_azure_endpoints_test.py @@ -1,10 +1,11 @@ import pytest -import typing import json import uuid from faker import Faker import azure.functions as func +import sqlalchemy +from sqlalchemy.sql.expression import true import time_entries._application._activities as azure_activities import time_entries._domain as domain @@ -18,24 +19,34 @@ def _create_fake_database() -> domain.ActivitiesDao: db_fake = infrastructure.DB('sqlite:///:memory:') demo_data = [ { - 'id': uuid.UUID('b4327ba6-9f96-49ee-a9ac-3c1edf525172'), - 'name': 'Activity Demo create', - 'description': 'test demo create an new activity', - 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', + 'id': Faker().uuid4(), + 'name': Faker().user_name(), + 'description': Faker().sentence(), + 'deleted': Faker().uuid4(), 'status': 'active', - 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', + 'tenant_id': Faker().uuid4(), }, - { - 'id': uuid.UUID('c61a4a49-3364-49a3-a7f7-0c5f2d15072b'), - 'name': 'Activity Demo create', - 'description': 'test demo create an new activity', - 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', + { + 'id': Faker().uuid4(), + 'name': Faker().user_name(), + 'description': Faker().sentence(), + 'deleted': Faker().uuid4(), 'status': 'active', - 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', + 'tenant_id': Faker().uuid4(), }, ] - - query = db_fake.activity.insert() + activity = sqlalchemy.Table('activity', db_fake.metadata, + sqlalchemy.Column('name', sqlalchemy.String), + sqlalchemy.Column('id', infrastructure.GUID(), primary_key=True, default=uuid.uuid4), + sqlalchemy.Column('description', sqlalchemy.String), + sqlalchemy.Column('deleted', sqlalchemy.String), + sqlalchemy.Column('status', sqlalchemy.String), + sqlalchemy.Column('tenant_id', sqlalchemy.String), + extend_existing=True, + ) + + query = activity.insert() + db_fake.get_session().execute(query, demo_data) return db_fake, demo_data @@ -50,7 +61,7 @@ def test__activity_azure_endpoint__returns_all_activities( activities_json_data = response.get_body().decode("utf-8") for activity in activity_data: - activity["id"] = activity["id"].hex + activity["id"] = uuid.UUID(activity["id"]).hex assert response.status_code == 200 assert activities_json_data == json.dumps(activity_data) @@ -71,7 +82,7 @@ def test__activity_azure_endpoint__returns_an_activity__when_activity_matches_it response = azure_activities._get_activities.get_activities(req) activitiy_json_data = response.get_body().decode("utf-8") - activity_data[0]["id"] = activity_data[0]["id"].hex + activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex assert response.status_code == 200 assert activitiy_json_data == json.dumps(activity_data[0]) @@ -86,7 +97,7 @@ def test__activity_azure_endpoint__returns_an_activity_with_inactive_status__whe method='DELETE', body=None, url=ACTIVITY_URL, - route_params={"id": str(activity_data[0]['id'])}, + route_params={"id": str(uuid.UUID(activity_data[0]['id']))}, ) response = azure_activities._delete_activity.delete_activity(req) @@ -106,10 +117,10 @@ def test__update_activity_azure_endpoint__returns_an_activity__when_found_an_act method='PUT', body=json.dumps(activity_body).encode("utf-8"), url=ACTIVITY_URL, - route_params={"id": str(activity_data[0]['id'])}, + route_params={"id": str(uuid.UUID(activity_data[0]['id']))}, ) - activity_data[0]["id"] = activity_data[0]["id"].hex + activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex response = azure_activities._update_activity.update_activity(req) activitiy_json_data = response.get_body().decode("utf-8") diff --git a/V2/tests/integration/daos/activities_sql_dao_test.py b/V2/tests/integration/daos/activities_sql_dao_test.py index fb598f46..44ceab37 100644 --- a/V2/tests/integration/daos/activities_sql_dao_test.py +++ b/V2/tests/integration/daos/activities_sql_dao_test.py @@ -1,158 +1,137 @@ import pytest import uuid +from faker import Faker import time_entries._domain as domain import time_entries._infrastructure as infrastructure - +import sqlalchemy @pytest.fixture(name='create_fake_database') def _create_fake_database(with_data: bool) -> domain.ActivitiesDao: db_fake = infrastructure.DB('sqlite:///:memory:') demo_data = [ { - 'id': uuid.UUID('b4327ba6-9f96-49ee-a9ac-3c1edf525172'), - 'name': 'Activity Demo create', - 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', - 'description': 'test demo create an new activity', + 'id': Faker().uuid4(), + 'name': Faker().user_name(), + 'description': Faker().sentence(), + 'deleted': Faker().uuid4(), 'status': 'active', - 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', + 'tenant_id': Faker().uuid4(), }, { - 'id': uuid.UUID('c61a4a49-3364-49a3-a7f7-0c5f2d15072b'), - 'name': 'Activity Demo create', - 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', - 'description': 'test demo create an new activity', + 'id': Faker().uuid4(), + 'name': Faker().user_name(), + 'description': Faker().sentence(), + 'deleted': Faker().uuid4(), 'status': 'active', - 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', + 'tenant_id': Faker().uuid4(), }, ] if with_data: - query = db_fake.activity.insert() + activity = sqlalchemy.Table('activity', db_fake.metadata, + sqlalchemy.Column('name', sqlalchemy.String), + sqlalchemy.Column('id', infrastructure.GUID(), primary_key=True, default=uuid.uuid4), + sqlalchemy.Column('description', sqlalchemy.String), + sqlalchemy.Column('deleted', sqlalchemy.String), + sqlalchemy.Column('status', sqlalchemy.String), + sqlalchemy.Column('tenant_id', sqlalchemy.String), + extend_existing=True, + ) + query = activity.insert() db_fake.get_session().execute(query, demo_data) - return db_fake + return db_fake, demo_data @pytest.mark.parametrize('with_data',[False]) def test__create_activity__returns_a_activity_dto__when_saves_correctly_with_sql_database(create_fake_database): - activity = { - 'name': 'Activity Demo create', - 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', - 'description': 'test demo create an new activity', - 'status': 'active', - 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', - } - dao = infrastructure.ActivitiesSQLDao(create_fake_database) - results = dao.create_activity(activity) + database, activity_data = create_fake_database + dao = infrastructure.ActivitiesSQLDao(database) + results = dao.create_activity(activity_data[0]) assert results.id != None @pytest.mark.parametrize('with_data',[True]) def test_update__returns_an_activity_updated__when_an_activity_matching_its_id_is_found_with_sql_database(create_fake_database): - activity = { + body = { 'name': 'Activity Demo create 3', 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', 'description': 'test demo create an new activity', 'status': 'active', 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', } - expected_result=domain.Activity(**{ - 'id': 'b4327ba69f9649eea9ac3c1edf525172', - 'name': 'Activity Demo create 3', - 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', - 'description': 'test demo create an new activity', - 'status': 'active', - 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', - }) - dao = infrastructure.ActivitiesSQLDao(create_fake_database) - results = dao.update('b4327ba69f9649eea9ac3c1edf525172',activity) + database, activity_data = create_fake_database + activity_data[0].update(body) + activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex + expected_result=domain.Activity(**activity_data[0]) + dao = infrastructure.ActivitiesSQLDao(database) + results = dao.update(activity_data[0]["id"],body) assert results == expected_result @pytest.mark.parametrize('with_data',[False]) def test_update__returns_none__when_no_activity_matching_its_id_is_found_with_sql_database(create_fake_database): - activity = { - 'name': 'Activity Demo create 3', - 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', - 'description': 'test demo create an new activity', - 'status': 'active', - 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', - } - dao = infrastructure.ActivitiesSQLDao(create_fake_database) - results = dao.update('b4327ba69f9649eea9ac3c1edf525172',activity) + database, activity_data = create_fake_database + activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex + dao = infrastructure.ActivitiesSQLDao(database) + results = dao.update(activity_data[0]["id"],activity_data[0]) assert results == None @pytest.mark.parametrize('with_data',[True]) def test__get_all__returns_a_list_of_activity_dto_objects__when_one_or_more_activities_are_found_with_sql_database(create_fake_database): + database, activity_data = create_fake_database + for activity in activity_data: + activity["id"] = uuid.UUID(activity["id"]).hex expected_result=[ - domain.Activity(**{ - 'id': 'b4327ba69f9649eea9ac3c1edf525172', - 'name': 'Activity Demo create', - 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', - 'description': 'test demo create an new activity', - 'status': 'active', - 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', - }), - domain.Activity(**{ - 'id': 'c61a4a49336449a3a7f70c5f2d15072b', - 'name': 'Activity Demo create', - 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', - 'description': 'test demo create an new activity', - 'status': 'active', - 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', - }), + domain.Activity(**activity_data[0]), + domain.Activity(**activity_data[1]), ] - dao = infrastructure.ActivitiesSQLDao(create_fake_database) + dao = infrastructure.ActivitiesSQLDao(database) results = dao.get_all() assert results == expected_result @pytest.mark.parametrize('with_data',[True]) def test_get_by_id__returns_an_activity_dto__when_found_one_activity_that_matches_its_id_with_sql_database(create_fake_database): - expected_result=domain.Activity(**{ - 'id': 'b4327ba69f9649eea9ac3c1edf525172', - 'name': 'Activity Demo create', - 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', - 'description': 'test demo create an new activity', - 'status': 'active', - 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', - }) - dao = infrastructure.ActivitiesSQLDao(create_fake_database) - results = dao.get_by_id('b4327ba69f9649eea9ac3c1edf525172') + database, activity_data = create_fake_database + activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex + expected_result=domain.Activity(**activity_data[0]) + dao = infrastructure.ActivitiesSQLDao(database) + results = dao.get_by_id(activity_data[0]["id"]) assert results == expected_result @pytest.mark.parametrize('with_data',[False]) def test__get_by_id__returns_none__when_no_activity_matches_its_id_with_sql_database(create_fake_database): - dao = infrastructure.ActivitiesSQLDao(create_fake_database) - results = dao.get_by_id('b4327ba69f9649eea9ac3c1edf525172') + database, activity_data = create_fake_database + activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex + dao = infrastructure.ActivitiesSQLDao(database) + results = dao.get_by_id(activity_data[0]["id"]) assert results == None @pytest.mark.parametrize('with_data',[False]) def test_get_all__returns_an_empty_list__when_doesnt_found_any_activities_with_sql_database(create_fake_database): - dao = infrastructure.ActivitiesSQLDao(create_fake_database) + database, activity_data = create_fake_database + dao = infrastructure.ActivitiesSQLDao(database) results = dao.get_all() assert results == [] @pytest.mark.parametrize('with_data',[True]) def test_delete__returns_an_activity_with_inactive_status__when_an_activity_matching_its_id_is_found_with_sql_database(create_fake_database): - expected_result=domain.Activity(**{ - 'id': 'b4327ba69f9649eea9ac3c1edf525172', - 'name': 'Activity Demo create', - 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', - 'description': 'test demo create an new activity', - 'status': 'inactive', - 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', - }) - dao = infrastructure.ActivitiesSQLDao(create_fake_database) - results = dao.delete('b4327ba69f9649eea9ac3c1edf525172') + database, activity_data = create_fake_database + activity_data[0].update({"id":uuid.UUID(activity_data[0]["id"]).hex,"status":"inactive"}) + expected_result=domain.Activity(**activity_data[0]) + dao = infrastructure.ActivitiesSQLDao(database) + results = dao.delete(activity_data[0]["id"]) assert results == expected_result @pytest.mark.parametrize('with_data',[False]) def test_delete__returns_none__when_no_activity_matching_its_id_is_found_with_sql_database(create_fake_database): - dao = infrastructure.ActivitiesSQLDao(create_fake_database) - results = dao.delete('b4327ba69f9649eea9ac3c1edf525172') + database, activity_data = create_fake_database + activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex + dao = infrastructure.ActivitiesSQLDao(database) + results = dao.delete(activity_data[0]["id"]) assert results == None \ No newline at end of file diff --git a/V2/time_entries/_application/_activities/_delete_activity.py b/V2/time_entries/_application/_activities/_delete_activity.py index ade9bff3..3eaa1d4c 100644 --- a/V2/time_entries/_application/_activities/_delete_activity.py +++ b/V2/time_entries/_application/_activities/_delete_activity.py @@ -1,12 +1,12 @@ import json import logging -from time_entries._infrastructure import ActivitiesSQLDao, DB -from time_entries._domain import ActivityService, _use_cases - import azure.functions as func -DATABASE = DB() +from ... import _domain +from ... import _infrastructure + +DATABASE = _infrastructure.DB() def delete_activity(req: func.HttpRequest) -> func.HttpResponse: @@ -23,13 +23,13 @@ def delete_activity(req: func.HttpRequest) -> func.HttpResponse: def _delete(activity_id: str) -> str: - activity_use_case = _use_cases.DeleteActivityUseCase( + activity_use_case = _domain._use_cases.DeleteActivityUseCase( _create_activity_service(DATABASE) ) activity = activity_use_case.delete_activity(activity_id) return json.dumps(activity.__dict__) if activity else b'Not found' -def _create_activity_service(db: DB): - activity_sql = ActivitiesSQLDao(db) - return ActivityService(activity_sql) +def _create_activity_service(db: _infrastructure.DB): + activity_sql = _infrastructure.ActivitiesSQLDao(db) + return _domain.ActivityService(activity_sql) diff --git a/V2/time_entries/_application/_activities/_get_activities.py b/V2/time_entries/_application/_activities/_get_activities.py index ff996634..d8594fa2 100644 --- a/V2/time_entries/_application/_activities/_get_activities.py +++ b/V2/time_entries/_application/_activities/_get_activities.py @@ -1,12 +1,12 @@ import json import logging -from time_entries._infrastructure import ActivitiesSQLDao, DB -from time_entries._domain import ActivityService, _use_cases - import azure.functions as func -DATABASE = DB() +from ... import _domain +from ... import _infrastructure + +DATABASE = _infrastructure.DB() def get_activities(req: func.HttpRequest) -> func.HttpResponse: @@ -29,7 +29,7 @@ def get_activities(req: func.HttpRequest) -> func.HttpResponse: def _get_by_id(activity_id: str) -> str: - activity_use_case = _use_cases.GetActivityUseCase( + activity_use_case = _domain._use_cases.GetActivityUseCase( _create_activity_service(DATABASE) ) activity = activity_use_case.get_activity_by_id(activity_id) @@ -38,7 +38,7 @@ def _get_by_id(activity_id: str) -> str: def _get_all() -> str: - activities_use_case = _use_cases.GetActivitiesUseCase( + activities_use_case = _domain._use_cases.GetActivitiesUseCase( _create_activity_service(DATABASE) ) return json.dumps( @@ -49,6 +49,6 @@ def _get_all() -> str: ) -def _create_activity_service(db: DB): - activity_sql = ActivitiesSQLDao(db) - return ActivityService(activity_sql) +def _create_activity_service(db: _infrastructure.DB): + activity_sql = _infrastructure.ActivitiesSQLDao(db) + return _domain.ActivityService(activity_sql) diff --git a/V2/time_entries/_application/_activities/_update_activity.py b/V2/time_entries/_application/_activities/_update_activity.py index d2947488..3c0e932a 100644 --- a/V2/time_entries/_application/_activities/_update_activity.py +++ b/V2/time_entries/_application/_activities/_update_activity.py @@ -1,12 +1,13 @@ -from time_entries._infrastructure import ActivitiesSQLDao, DB -from time_entries._domain import ActivityService, Activity, _use_cases - -import azure.functions as func import dataclasses import json import logging -DATABASE = DB() +import azure.functions as func + +from ... import _domain +from ... import _infrastructure + +DATABASE = _infrastructure.DB() def update_activity(req: func.HttpRequest) -> func.HttpResponse: @@ -15,7 +16,7 @@ def update_activity(req: func.HttpRequest) -> func.HttpResponse: ) activity_id = req.route_params.get('id') activity_data = req.get_json() if req.get_body() else {} - activity_keys = [field.name for field in dataclasses.fields(Activity)] + activity_keys = [field.name for field in dataclasses.fields(_domain.Activity)] if all(key in activity_keys for key in activity_data.keys()): response = _update(activity_id, activity_data) @@ -30,13 +31,13 @@ def update_activity(req: func.HttpRequest) -> func.HttpResponse: def _update(activity_id: str, activity_data: dict) -> str: - activity_use_case = _use_cases.UpdateActivityUseCase( + activity_use_case = _domain._use_cases.UpdateActivityUseCase( _create_activity_service(DATABASE) ) activity = activity_use_case.update_activity(activity_id, activity_data) return json.dumps(activity.__dict__) if activity else b'Not Found' -def _create_activity_service(db: DB): - activity_sql = ActivitiesSQLDao(db) - return ActivityService(activity_sql) +def _create_activity_service(db: _infrastructure.DB): + activity_sql = _infrastructure.ActivitiesSQLDao(db) + return _domain.ActivityService(activity_sql) diff --git a/V2/time_entries/_domain/_persistence_contracts/_activities_dao.py b/V2/time_entries/_domain/_persistence_contracts/_activities_dao.py index 2037841d..48d96ad4 100644 --- a/V2/time_entries/_domain/_persistence_contracts/_activities_dao.py +++ b/V2/time_entries/_domain/_persistence_contracts/_activities_dao.py @@ -22,8 +22,4 @@ def update(self, id: str, new_activity: dict) -> Activity: @abc.abstractmethod def create_activity(self, activity_data: dict) -> Activity: - pass - - @abc.abstractmethod - def delete(self, id: str) -> Activity: - pass + pass \ No newline at end of file diff --git a/V2/time_entries/_infrastructure/__init__.py b/V2/time_entries/_infrastructure/__init__.py index 162789a4..25c3493a 100644 --- a/V2/time_entries/_infrastructure/__init__.py +++ b/V2/time_entries/_infrastructure/__init__.py @@ -1,3 +1,4 @@ from ._data_persistence import ActivitiesSQLDao from ._data_persistence import DB +from ._data_persistence import GUID from ._data_persistence import Config \ No newline at end of file diff --git a/V2/time_entries/_infrastructure/_data_persistence/__init__.py b/V2/time_entries/_infrastructure/_data_persistence/__init__.py index b196882d..69fd2b8c 100644 --- a/V2/time_entries/_infrastructure/_data_persistence/__init__.py +++ b/V2/time_entries/_infrastructure/_data_persistence/__init__.py @@ -1,3 +1,3 @@ from ._activities_sql_dao import ActivitiesSQLDao -from ._db import DB +from ._db import DB, GUID from ._config import Config diff --git a/V2/time_entries/_infrastructure/_data_persistence/_activities_sql_dao.py b/V2/time_entries/_infrastructure/_data_persistence/_activities_sql_dao.py index f4ce2085..4c5e9d1f 100644 --- a/V2/time_entries/_infrastructure/_data_persistence/_activities_sql_dao.py +++ b/V2/time_entries/_infrastructure/_data_persistence/_activities_sql_dao.py @@ -1,24 +1,37 @@ import dataclasses import typing +import uuid +import sqlalchemy import sqlalchemy.sql as sql import time_entries._domain as domain +from . import _db + class ActivitiesSQLDao(domain.ActivitiesDao): - def __init__(self,database): + def __init__(self, database: _db.DB): self.activity_keys = [ field.name for field in dataclasses.fields(domain.Activity) ] self.db = database + self.activity = sqlalchemy.Table('activity', self.db.metadata, + sqlalchemy.Column('id',_db.GUID() , primary_key=True,default= uuid.uuid4), + sqlalchemy.Column('name', sqlalchemy.String), + sqlalchemy.Column('description', sqlalchemy.String), + sqlalchemy.Column('deleted', sqlalchemy.String), + sqlalchemy.Column('status', sqlalchemy.String), + sqlalchemy.Column('tenant_id', sqlalchemy.String), + extend_existing=True, + ) def get_by_id(self, activity_id: str) -> domain.Activity: - query = sql.select(self.db.activity).where(self.db.activity.c.id == activity_id) + query = sql.select(self.activity).where(self.activity.c.id == activity_id) activity = self.db.get_session().execute(query).one_or_none() return self.__create_activity_dto(dict(activity)) if activity else None def get_all(self) -> typing.List[domain.Activity]: - query = sql.select(self.db.activity) + query = sql.select(self.activity) result = self.db.get_session().execute(query) return [ self.__create_activity_dto(dict(activity)) @@ -28,18 +41,18 @@ def get_all(self) -> typing.List[domain.Activity]: def create_activity(self, activity_data: dict) -> domain.Activity: activity_data.pop('id', None) activity_data.update({"status":"active"}) - query = self.db.activity.insert().values(activity_data) + query = self.activity.insert().values(activity_data) activity = self.db.get_session().execute(query) return self.__create_activity_dto(activity.last_inserted_params()) def delete(self, activity_id: str) -> domain.Activity: - query = self.db.activity.update().where(self.db.activity.c.id == activity_id).values(status = 'inactive') + query = self.activity.update().where(self.activity.c.id == activity_id).values(status = 'inactive') self.db.get_session().execute(query) - return self.get_by_id(activity_id); + return self.get_by_id(activity_id) def update(self, activity_id: str, new_activity: dict) -> domain.Activity: new_activity.pop('id', None) - query = self.db.activity.update().where(self.db.activity.c.id==activity_id).values(new_activity) + query = self.activity.update().where(self.activity.c.id==activity_id).values(new_activity) self.db.get_session().execute(query) return self.get_by_id(activity_id) diff --git a/V2/time_entries/_infrastructure/_data_persistence/_config.py b/V2/time_entries/_infrastructure/_data_persistence/_config.py index 5776aff2..7ea24ce9 100644 --- a/V2/time_entries/_infrastructure/_data_persistence/_config.py +++ b/V2/time_entries/_infrastructure/_data_persistence/_config.py @@ -1,23 +1,11 @@ import typing import os -_CONFIG_FILE = '.env' - - class Config(typing.NamedTuple): DB_CONNECTION_STRING: str DB_USER: str DB_PASS: str DB_NAME: str - -def load_config(): - with open(_CONFIG_FILE, 'r') as config_file: - configs = { - config.split('=')[0]: config.split('=')[1].replace('\n', '') - for config in config_file.readlines() - } - return Config(**configs) - def load_config_os(): return Config(os.environ.get("DB_CONNECTION_STRING"),os.environ.get("DB_USER"),os.environ.get("DB_PASS"),os.environ.get("DB_NAME")) \ No newline at end of file diff --git a/V2/time_entries/_infrastructure/_data_persistence/_db.py b/V2/time_entries/_infrastructure/_data_persistence/_db.py index da5d045c..201493af 100644 --- a/V2/time_entries/_infrastructure/_data_persistence/_db.py +++ b/V2/time_entries/_infrastructure/_data_persistence/_db.py @@ -4,8 +4,9 @@ import sqlalchemy.dialects.postgresql as postgresql import sqlalchemy -from ._config import load_config_os +from . import _config +DIALECT = 'postgresql' class GUID(types.TypeDecorator): """Platform-independent GUID type. @@ -15,7 +16,7 @@ class GUID(types.TypeDecorator): impl = types.CHAR def load_dialect_impl(self, dialect): - if dialect.name == 'postgresql': + if dialect.name == DIALECT: return dialect.type_descriptor(postgresql.UUID()) else: return dialect.type_descriptor(types.CHAR(32)) @@ -23,7 +24,7 @@ def load_dialect_impl(self, dialect): def process_bind_param(self, value, dialect): if value is None: return value - elif dialect.name == 'postgresql': + elif dialect.name == DIALECT: return str(value) else: if not isinstance(value, uuid.UUID): @@ -41,19 +42,11 @@ def process_result_value(self, value, dialect): return value class DB(): - config = load_config_os() + config = _config.load_config_os() connection = None engine = None conn_string = config.DB_CONNECTION_STRING metadata = sqlalchemy.MetaData() - activity = sqlalchemy.Table('activity', metadata, - sqlalchemy.Column('id',GUID() , primary_key=True,default= uuid.uuid4), - sqlalchemy.Column('name', sqlalchemy.String), - sqlalchemy.Column('description', sqlalchemy.String), - sqlalchemy.Column('deleted', sqlalchemy.String), - sqlalchemy.Column('status', sqlalchemy.String), - sqlalchemy.Column('tenant_id', sqlalchemy.String), - ) def __init__(self, conn_string: str = conn_string): self.engine = sqlalchemy.create_engine(conn_string) From c353fb4664bfcc0e881644f5d563f7623bf71e05 Mon Sep 17 00:00:00 2001 From: Alexander Date: Thu, 4 Nov 2021 19:04:03 -0500 Subject: [PATCH 2/2] refactor: TT-357 remove duplication lines --- .../azure/activity_azure_endpoints_test.py | 48 +++--- .../daos/activities_sql_dao_test.py | 145 +++++++++++------- 2 files changed, 107 insertions(+), 86 deletions(-) diff --git a/V2/tests/api/azure/activity_azure_endpoints_test.py b/V2/tests/api/azure/activity_azure_endpoints_test.py index 1cbafb17..5d5d5469 100644 --- a/V2/tests/api/azure/activity_azure_endpoints_test.py +++ b/V2/tests/api/azure/activity_azure_endpoints_test.py @@ -5,7 +5,6 @@ import azure.functions as func import sqlalchemy -from sqlalchemy.sql.expression import true import time_entries._application._activities as azure_activities import time_entries._domain as domain @@ -13,28 +12,28 @@ ACTIVITY_URL = '/api/activities/' - @pytest.fixture(name='create_fake_database') def _create_fake_database() -> domain.ActivitiesDao: db_fake = infrastructure.DB('sqlite:///:memory:') demo_data = [ { - 'id': Faker().uuid4(), - 'name': Faker().user_name(), - 'description': Faker().sentence(), - 'deleted': Faker().uuid4(), + 'id': uuid.UUID('b4327ba6-9f96-49ee-a9ac-3c1edf525172'), + 'name': 'Activity Demo create', + 'description': 'test demo create an new activity', + 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', 'status': 'active', - 'tenant_id': Faker().uuid4(), + 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', }, - { - 'id': Faker().uuid4(), - 'name': Faker().user_name(), - 'description': Faker().sentence(), - 'deleted': Faker().uuid4(), + { + 'id': uuid.UUID('c61a4a49-3364-49a3-a7f7-0c5f2d15072b'), + 'name': 'Activity Demo create', + 'description': 'test demo create an new activity', + 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', 'status': 'active', - 'tenant_id': Faker().uuid4(), + 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', }, ] + activity = sqlalchemy.Table('activity', db_fake.metadata, sqlalchemy.Column('name', sqlalchemy.String), sqlalchemy.Column('id', infrastructure.GUID(), primary_key=True, default=uuid.uuid4), @@ -50,18 +49,18 @@ def _create_fake_database() -> domain.ActivitiesDao: db_fake.get_session().execute(query, demo_data) return db_fake, demo_data + def test__activity_azure_endpoint__returns_all_activities( create_fake_database, ): database, activity_data = create_fake_database azure_activities._get_activities.DATABASE = database req = func.HttpRequest(method='GET', body=None, url=ACTIVITY_URL) - response = azure_activities._get_activities.get_activities(req) activities_json_data = response.get_body().decode("utf-8") for activity in activity_data: - activity["id"] = uuid.UUID(activity["id"]).hex + activity["id"] = activity["id"].hex assert response.status_code == 200 assert activities_json_data == json.dumps(activity_data) @@ -78,12 +77,9 @@ def test__activity_azure_endpoint__returns_an_activity__when_activity_matches_it url=ACTIVITY_URL, route_params={"id": str(activity_data[0]['id'])}, ) - response = azure_activities._get_activities.get_activities(req) activitiy_json_data = response.get_body().decode("utf-8") - - activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex - + activity_data[0]["id"] = activity_data[0]["id"].hex assert response.status_code == 200 assert activitiy_json_data == json.dumps(activity_data[0]) @@ -97,12 +93,10 @@ def test__activity_azure_endpoint__returns_an_activity_with_inactive_status__whe method='DELETE', body=None, url=ACTIVITY_URL, - route_params={"id": str(uuid.UUID(activity_data[0]['id']))}, + route_params={"id": str(activity_data[0]['id'])}, ) - response = azure_activities._delete_activity.delete_activity(req) activity_json_data = json.loads(response.get_body().decode("utf-8")) - assert response.status_code == 200 assert activity_json_data['status'] == 'inactive' @@ -117,24 +111,21 @@ def test__update_activity_azure_endpoint__returns_an_activity__when_found_an_act method='PUT', body=json.dumps(activity_body).encode("utf-8"), url=ACTIVITY_URL, - route_params={"id": str(uuid.UUID(activity_data[0]['id']))}, + route_params={"id": str(activity_data[0]['id'])}, ) - - activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex - + activity_data[0]["id"] = activity_data[0]["id"].hex response = azure_activities._update_activity.update_activity(req) activitiy_json_data = response.get_body().decode("utf-8") new_activity = {**activity_data[0], **activity_body} - assert response.status_code == 200 assert activitiy_json_data == json.dumps(new_activity) + def test__activity_azure_endpoint__creates_an_activity__when_activity_has_all_attributes( create_fake_database, ): database, activity_data = create_fake_database azure_activities._create_activity.DATABASE = database - activity_body = {'id': None, 'name': Faker().user_name(), 'description': Faker().sentence(),'deleted': Faker().uuid4() ,'status': 'active', 'tenant_id': Faker().uuid4()} body = json.dumps(activity_body).encode("utf-8") req = func.HttpRequest( @@ -143,7 +134,6 @@ def test__activity_azure_endpoint__creates_an_activity__when_activity_has_all_at url=ACTIVITY_URL, ) - response = azure_activities._create_activity.create_activity(req) activitiy_json_data = json.loads(response.get_body()) activity_body['id'] = activitiy_json_data['id'] diff --git a/V2/tests/integration/daos/activities_sql_dao_test.py b/V2/tests/integration/daos/activities_sql_dao_test.py index 44ceab37..d0c469a1 100644 --- a/V2/tests/integration/daos/activities_sql_dao_test.py +++ b/V2/tests/integration/daos/activities_sql_dao_test.py @@ -1,30 +1,30 @@ import pytest import uuid -from faker import Faker + +import sqlalchemy import time_entries._domain as domain import time_entries._infrastructure as infrastructure -import sqlalchemy @pytest.fixture(name='create_fake_database') def _create_fake_database(with_data: bool) -> domain.ActivitiesDao: db_fake = infrastructure.DB('sqlite:///:memory:') demo_data = [ { - 'id': Faker().uuid4(), - 'name': Faker().user_name(), - 'description': Faker().sentence(), - 'deleted': Faker().uuid4(), + 'id': uuid.UUID('b4327ba6-9f96-49ee-a9ac-3c1edf525172'), + 'name': 'Activity Demo create', + 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', + 'description': 'test demo create an new activity', 'status': 'active', - 'tenant_id': Faker().uuid4(), + 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', }, { - 'id': Faker().uuid4(), - 'name': Faker().user_name(), - 'description': Faker().sentence(), - 'deleted': Faker().uuid4(), + 'id': uuid.UUID('c61a4a49-3364-49a3-a7f7-0c5f2d15072b'), + 'name': 'Activity Demo create', + 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', + 'description': 'test demo create an new activity', 'status': 'active', - 'tenant_id': Faker().uuid4(), + 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', }, ] if with_data: @@ -39,99 +39,130 @@ def _create_fake_database(with_data: bool) -> domain.ActivitiesDao: ) query = activity.insert() db_fake.get_session().execute(query, demo_data) - return db_fake, demo_data + return db_fake @pytest.mark.parametrize('with_data',[False]) def test__create_activity__returns_a_activity_dto__when_saves_correctly_with_sql_database(create_fake_database): - database, activity_data = create_fake_database - dao = infrastructure.ActivitiesSQLDao(database) - results = dao.create_activity(activity_data[0]) - assert results.id != None - + activity = { + 'name': 'Activity Demo create', + 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', + 'description': 'test demo create an new activity', + 'status': 'active', + 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', + } + dao = infrastructure.ActivitiesSQLDao(create_fake_database) + results = dao.create_activity(activity) + assert results.id != None\ + @pytest.mark.parametrize('with_data',[True]) def test_update__returns_an_activity_updated__when_an_activity_matching_its_id_is_found_with_sql_database(create_fake_database): - body = { + activity = { 'name': 'Activity Demo create 3', 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', 'description': 'test demo create an new activity', 'status': 'active', 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', } - database, activity_data = create_fake_database - activity_data[0].update(body) - activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex - expected_result=domain.Activity(**activity_data[0]) - dao = infrastructure.ActivitiesSQLDao(database) - results = dao.update(activity_data[0]["id"],body) + expected_result=domain.Activity(**{ + 'id': 'b4327ba69f9649eea9ac3c1edf525172', + 'name': 'Activity Demo create 3', + 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', + 'description': 'test demo create an new activity', + 'status': 'active', + 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', + }) + dao = infrastructure.ActivitiesSQLDao(create_fake_database) + results = dao.update('b4327ba69f9649eea9ac3c1edf525172',activity) assert results == expected_result @pytest.mark.parametrize('with_data',[False]) def test_update__returns_none__when_no_activity_matching_its_id_is_found_with_sql_database(create_fake_database): - database, activity_data = create_fake_database - activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex - dao = infrastructure.ActivitiesSQLDao(database) - results = dao.update(activity_data[0]["id"],activity_data[0]) + activity = { + 'name': 'Activity Demo create 3', + 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', + 'description': 'test demo create an new activity', + 'status': 'active', + 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', + } + dao = infrastructure.ActivitiesSQLDao(create_fake_database) + results = dao.update('b4327ba69f9649eea9ac3c1edf525172',activity) assert results == None - + @pytest.mark.parametrize('with_data',[True]) def test__get_all__returns_a_list_of_activity_dto_objects__when_one_or_more_activities_are_found_with_sql_database(create_fake_database): - database, activity_data = create_fake_database - for activity in activity_data: - activity["id"] = uuid.UUID(activity["id"]).hex expected_result=[ - domain.Activity(**activity_data[0]), - domain.Activity(**activity_data[1]), + domain.Activity(**{ + 'id': 'b4327ba69f9649eea9ac3c1edf525172', + 'name': 'Activity Demo create', + 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', + 'description': 'test demo create an new activity', + 'status': 'active', + 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', + }), + domain.Activity(**{ + 'id': 'c61a4a49336449a3a7f70c5f2d15072b', + 'name': 'Activity Demo create', + 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', + 'description': 'test demo create an new activity', + 'status': 'active', + 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', + }), ] - dao = infrastructure.ActivitiesSQLDao(database) + dao = infrastructure.ActivitiesSQLDao(create_fake_database) results = dao.get_all() assert results == expected_result @pytest.mark.parametrize('with_data',[True]) def test_get_by_id__returns_an_activity_dto__when_found_one_activity_that_matches_its_id_with_sql_database(create_fake_database): - database, activity_data = create_fake_database - activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex - expected_result=domain.Activity(**activity_data[0]) - dao = infrastructure.ActivitiesSQLDao(database) - results = dao.get_by_id(activity_data[0]["id"]) + expected_result=domain.Activity(**{ + 'id': 'b4327ba69f9649eea9ac3c1edf525172', + 'name': 'Activity Demo create', + 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', + 'description': 'test demo create an new activity', + 'status': 'active', + 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', + }) + dao = infrastructure.ActivitiesSQLDao(create_fake_database) + results = dao.get_by_id('b4327ba69f9649eea9ac3c1edf525172') assert results == expected_result @pytest.mark.parametrize('with_data',[False]) def test__get_by_id__returns_none__when_no_activity_matches_its_id_with_sql_database(create_fake_database): - database, activity_data = create_fake_database - activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex - dao = infrastructure.ActivitiesSQLDao(database) - results = dao.get_by_id(activity_data[0]["id"]) + dao = infrastructure.ActivitiesSQLDao(create_fake_database) + results = dao.get_by_id('b4327ba69f9649eea9ac3c1edf525172') assert results == None @pytest.mark.parametrize('with_data',[False]) def test_get_all__returns_an_empty_list__when_doesnt_found_any_activities_with_sql_database(create_fake_database): - database, activity_data = create_fake_database - dao = infrastructure.ActivitiesSQLDao(database) + dao = infrastructure.ActivitiesSQLDao(create_fake_database) results = dao.get_all() assert results == [] @pytest.mark.parametrize('with_data',[True]) def test_delete__returns_an_activity_with_inactive_status__when_an_activity_matching_its_id_is_found_with_sql_database(create_fake_database): - database, activity_data = create_fake_database - activity_data[0].update({"id":uuid.UUID(activity_data[0]["id"]).hex,"status":"inactive"}) - expected_result=domain.Activity(**activity_data[0]) - dao = infrastructure.ActivitiesSQLDao(database) - results = dao.delete(activity_data[0]["id"]) + expected_result=domain.Activity(**{ + 'id': 'b4327ba69f9649eea9ac3c1edf525172', + 'name': 'Activity Demo create', + 'tenant_id': 'cc925a5d-9644-4a4f-8d99-0bee49aadd05', + 'description': 'test demo create an new activity', + 'status': 'inactive', + 'deleted': 'b4327ba6-9f96-49ee-a9ac-3c1edf525172', + }) + dao = infrastructure.ActivitiesSQLDao(create_fake_database) + results = dao.delete('b4327ba69f9649eea9ac3c1edf525172') assert results == expected_result - + @pytest.mark.parametrize('with_data',[False]) def test_delete__returns_none__when_no_activity_matching_its_id_is_found_with_sql_database(create_fake_database): - database, activity_data = create_fake_database - activity_data[0]["id"] = uuid.UUID(activity_data[0]["id"]).hex - dao = infrastructure.ActivitiesSQLDao(database) - results = dao.delete(activity_data[0]["id"]) + dao = infrastructure.ActivitiesSQLDao(create_fake_database) + results = dao.delete('b4327ba69f9649eea9ac3c1edf525172') assert results == None \ No newline at end of file