Skip to content
Prev Previous commit
Next Next commit
refactor: TT-353 Solving requested changes on PR
  • Loading branch information
Andrés Soto committed Sep 30, 2021
commit 1f92569eac52327760f89b8d8f8d6fc607570664
13 changes: 13 additions & 0 deletions V2/source/daos/activities_dao.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from V2.source.dtos.activity import Activity
import abc
import typing


class ActivitiesDao(abc.ABC):
@abc.abstractmethod
def get_by_id(self, id: str) -> Activity:
pass

@abc.abstractmethod
def get_all(self) -> typing.List[Activity]:
pass
12 changes: 0 additions & 12 deletions V2/source/daos/activities_dao_interface.py

This file was deleted.

56 changes: 24 additions & 32 deletions V2/source/daos/activities_json_dao.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,35 @@
from V2.source.daos.activities_dao_interface import ActivitiesDaoInterface
from V2.source.dtos.activity import ActivityDto
from http import HTTPStatus
from V2.source.daos.activities_dao import ActivitiesDao
from V2.source.dtos.activity import Activity
import json
import typing


class ActivitiesJsonDao(ActivitiesDaoInterface):
class ActivitiesJsonDao(ActivitiesDao):
def __init__(self, json_data_file_path: str):
self.json_data_file_path = json_data_file_path
self.activity_keys = ActivityDto.__dataclass_fields__.keys()

def get_by_id(self, id: str) -> ActivityDto:
activities = self.__get_activities_from_file()

try:
activity = next(
(
activity
for activity in activities
if activity.get('id') == id
)
)
except Exception:
return HTTPStatus.NOT_FOUND

activity_dto = self.__create_activity_dto(activity)
self.activity_keys = Activity.__dataclass_fields__.keys()

def get_by_id(self, activity_id: str) -> Activity:
activities_grouped_by_id = {
activity.get('id'): activity
for activity in self.__get_activities_from_file()
}
activity = activities_grouped_by_id.get(activity_id)
activity_dto = (
self.__create_activity_dto(activity) if activity else None
)

return activity_dto

def get_all(self) -> list:
activities = self.__get_activities_from_file()
list_activities = []

for activity in activities:
activity = self.__create_activity_dto(activity)
list_activities.append(activity)
def get_all(self) -> typing.List[Activity]:
all_activities = self.__get_activities_from_file()
activity_dtos = [
self.__create_activity_dto(activity) for activity in all_activities
]

return list_activities
return activity_dtos

def __get_activities_from_file(self) -> list:
def __get_activities_from_file(self) -> typing.List[dict]:
try:
file = open(self.json_data_file_path)
activities = json.load(file)
Expand All @@ -48,7 +40,7 @@ def __get_activities_from_file(self) -> list:
except FileNotFoundError:
return []

def __create_activity_dto(self, activity: dict) -> ActivityDto:
def __create_activity_dto(self, activity: dict) -> Activity:
activity = {key: activity.get(key) for key in self.activity_keys}
activity_dto = ActivityDto(**activity)
activity_dto = Activity(**activity)
return activity_dto
2 changes: 1 addition & 1 deletion V2/source/dtos/activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


@dataclass(frozen=True)
class ActivityDto:
class Activity:
id: str
name: str
description: str
Expand Down
17 changes: 8 additions & 9 deletions V2/source/services/activity_service.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
from V2.source.daos.activities_dao_interface import ActivitiesDaoInterface
from V2.source.dtos.activity import ActivityDto
from V2.source.daos.activities_dao import ActivitiesDao
from V2.source.dtos.activity import Activity
import typing


class ActivityService:
def __init__(self, activities_dao: ActivitiesDaoInterface):
def __init__(self, activities_dao: ActivitiesDao):
self.activities_dao = activities_dao

def get_by_id(self, id: str) -> ActivityDto:
activity_dto = self.activities_dao.get_by_id(id)
return activity_dto
def get_by_id(self, activity_id: str) -> Activity:
return self.activities_dao.get_by_id(activity_id)

def get_all(self) -> list:
list_activities = self.activities_dao.get_all()
return list_activities
def get_all(self) -> typing.List[Activity]:
return self.activities_dao.get_all()
107 changes: 57 additions & 50 deletions V2/tests/daos/activities_json_dao_test.py
Original file line number Diff line number Diff line change
@@ -1,78 +1,85 @@
from V2.source.daos.activities_json_dao import ActivitiesJsonDao
from V2.source.dtos.activity import ActivityDto
from http import HTTPStatus
from V2.source.dtos.activity import Activity
from faker import Faker
import json
import pytest
import typing


OPEN_FILE = 'builtins.open'
@pytest.fixture(name='create_fake_activities')
def _create_fake_activities(mocker) -> typing.List[Activity]:
def _creator(activities):
read_data = json.dumps(activities)
mocker.patch('builtins.open', mocker.mock_open(read_data=read_data))
return [Activity(**activity) for activity in activities]

return _creator

def test_get_by_id__return_activity_dto__when_find_activity_that_matches_its_id(
mocker,

def test_get_by_id__returns_an_activity_dto__when_found_one_activity_that_matches_its_id(
create_fake_activities,
):
activities_json_dao = ActivitiesJsonDao('non-important-path')
activities = [
{
"name": "test_name",
"description": "test_description",
"tenant_id": "test_tenant_id",
"id": "test_id",
"deleted": "test_deleted",
"status": "test_status",
}
]
read_data = json.dumps(activities)
activity_dto = ActivityDto(**activities.pop())

mocker.patch(OPEN_FILE, mocker.mock_open(read_data=read_data))
activities_json_dao = ActivitiesJsonDao(Faker().file_path())
activities = create_fake_activities(
[
{
"name": "test_name",
"description": "test_description",
"tenant_id": "test_tenant_id",
"id": "test_id",
"deleted": "test_deleted",
"status": "test_status",
}
]
)
activity_dto = activities.pop()

result = activities_json_dao.get_by_id(activity_dto.id)

assert result == activity_dto


def test__get_by_id__return_httpstatus_not_found__when_no_activity_matches_its_id(
mocker,
def test__get_by_id__returns_none__when_no_activity_matches_its_id(
create_fake_activities,
):
activities_json_dao = ActivitiesJsonDao('non-important-path')
activities = []
read_data = json.dumps(activities)
activities_json_dao = ActivitiesJsonDao(Faker().file_path())
create_fake_activities([])

mocker.patch(OPEN_FILE, mocker.mock_open(read_data=read_data))
result = activities_json_dao.get_by_id('non-important-id')
result = activities_json_dao.get_by_id(Faker().uuid4())

assert result == HTTPStatus.NOT_FOUND
assert result == None


def test_get_all__return_list_of_activity_dto__when_find_one_or_more_activities(
mocker,
def test__get_all__returns_a_list_of_activity_dto_objects__when_one_or_more_activities_are_found(
create_fake_activities,
):
activities_json_dao = ActivitiesJsonDao('non-important-path')
activity = {
"name": "test_name",
"description": "test_description",
"tenant_id": "test_tenant_id",
"id": "test_id",
"deleted": "test_deleted",
"status": "test_status",
}
activities_json_dao = ActivitiesJsonDao(Faker().file_path())
number_of_activities = 3
activity_dto = ActivityDto(**activity)
list_activities_dto = [activity_dto] * number_of_activities
activities = [activity] * number_of_activities
read_data = json.dumps(activities)
activities = create_fake_activities(
[
{
"name": "test_name",
"description": "test_description",
"tenant_id": "test_tenant_id",
"id": "test_id",
"deleted": "test_deleted",
"status": "test_status",
}
]
* number_of_activities
)

mocker.patch(OPEN_FILE, mocker.mock_open(read_data=read_data))
result = activities_json_dao.get_all()

assert result == list_activities_dto
assert result == activities


def test_get_all__return_empty_list__when_doesnt_found_any_activities(mocker):
activities_json_dao = ActivitiesJsonDao('non-important-path')
activities = []
read_data = json.dumps(activities)
def test_get_all__returns_an_empty_list__when_doesnt_found_any_activities(
create_fake_activities,
):
activities_json_dao = ActivitiesJsonDao(Faker().file_path())
activities = create_fake_activities([])

mocker.patch(OPEN_FILE, mocker.mock_open(read_data=read_data))
result = activities_json_dao.get_all()

assert result == activities
88 changes: 17 additions & 71 deletions V2/tests/services/activity_service_test.py
Original file line number Diff line number Diff line change
@@ -1,82 +1,28 @@
from V2.source.services.activity_service import ActivityService
from V2.source.daos.activities_dao_interface import ActivitiesDaoInterface
from V2.source.dtos.activity import ActivityDto
from http import HTTPStatus
from faker import Faker


def test__get_by_id__return_activity_dto__when_find_activity_that_matches_its_id(
mocker,
):
activity_service = ActivityService(ActivitiesDaoInterface)
activity = {
"name": "test_name",
"description": "test_description",
"tenant_id": "test_tenant_id",
"id": "test_id",
"deleted": "test_deleted",
"status": "test_status",
}
activity_dto = ActivityDto(**activity)

activities_dao_mock = mocker.patch.object(
ActivitiesDaoInterface, 'get_by_id'
def test__get_all__uses_the_activity_dao__to_retrieve_activities(mocker):
expected_activities = mocker.Mock()
activity_dao = mocker.Mock(
get_all=mocker.Mock(return_value=expected_activities)
)
activities_dao_mock.return_value = activity_dto
result = activity_service.get_by_id(activity.get('id'))
activity_service = ActivityService(activity_dao)

assert result == activity_dto
actual_activities = activity_service.get_all()

assert activity_dao.get_all.called
assert expected_activities == actual_activities

def test__get_by_id__return_httpstatus_not_found__when_no_activity_matches_its_id(
mocker,
):
activity_service = ActivityService(ActivitiesDaoInterface)

activities_dao_mock = mocker.patch.object(
ActivitiesDaoInterface, 'get_by_id'
def test__get_by_id__uses_the_activity_dao__to_retrieve_one_ativity(mocker):
expected_activity = mocker.Mock()
activity_dao = mocker.Mock(
get_by_id=mocker.Mock(return_value=expected_activity)
)
activities_dao_mock.return_value = HTTPStatus.NOT_FOUND

result = activity_service.get_by_id('non-important-id')

assert result == HTTPStatus.NOT_FOUND
activity_service = ActivityService(activity_dao)

actual_activity = activity_service.get_by_id(Faker().uuid4())

def test__get_all__return_list_of_activity_dto__when_find_one_or_more_activities(
mocker,
):
activity_service = ActivityService(ActivitiesDaoInterface)
activity = {
"name": "test_name",
"description": "test_description",
"tenant_id": "test_tenant_id",
"id": "test_id",
"deleted": "test_deleted",
"status": "test_status",
}
number_of_activities = 3
activity_dto = ActivityDto(**activity)
list_activities_dto = [activity_dto] * number_of_activities

activities_dao_mock = mocker.patch.object(
ActivitiesDaoInterface, 'get_all'
)
activities_dao_mock.return_value = list_activities_dto
result = activity_service.get_all()

assert result == list_activities_dto


def test__get_all__return_empty_list__when_doesnt_found_any_activities(
mocker,
):
activity_service = ActivityService(ActivitiesDaoInterface)
activities = []

activities_dao_mock = mocker.patch.object(
ActivitiesDaoInterface, 'get_all'
)
activities_dao_mock.return_value = activities
result = activity_service.get_all()

assert result == activities
assert activity_dao.get_by_id.called
assert expected_activity == actual_activity