StorageRoom
model. As mentioned earlier, models in pure architecture are very light, at least easier than their ORM counterparts in frameworks.tests/domain/test_storageroom.py
and place this code inside it: import uuid from rentomatic.domain.storageroom import StorageRoom def test_storageroom_model_init(): code = uuid.uuid4() storageroom = StorageRoom(code, size=200, price=10, longitude='-0.09998975', latitude='51.75436293') assert storageroom.code == code assert storageroom.size == 200 assert storageroom.price == 10 assert storageroom.longitude == -0.09998975 assert storageroom.latitude == 51.75436293 def test_storageroom_model_from_dict(): code = uuid.uuid4() storageroom = StorageRoom.from_dict( { 'code': code, 'size': 200, 'price': 10, 'longitude': '-0.09998975', 'latitude': '51.75436293' } ) assert storageroom.code == code assert storageroom.size == 200 assert storageroom.price == 10 assert storageroom.longitude == -0.09998975 assert storageroom.latitude == 51.75436293
StorageRoom
class by placing it in the rentomatic/domain/storageroom.py
. Do not forget to create a file __init__.py
in each subdirectory of the project, which Python should perceive as modules. from rentomatic.shared.domain_model import DomainModel class StorageRoom(object): def __init__(self, code, size, price, latitude, longitude): self.code = code self.size = size self.price = price self.latitude = float(latitude) self.longitude = float(longitude) @classmethod def from_dict(cls, adict): room = StorageRoom( code=adict['code'], size=adict['size'], price=adict['price'], latitude=adict['latitude'], longitude=adict['longitude'], ) return room DomainModel.register(StorageRoom)
from_dict
method from_dict
useful when creating a model from data coming from another layer (such as a database layer or from a query string in a REST layer).from_dict
function by abstracting and presenting it as a method of the Model class. And considering that a certain level of abstraction and generalization is possible and necessary, and the initialization of models can interact with various other scenarios, it is better to implement it directly in the class itself.DomainModel
abstract base class is an easy way to classify a model for future scenarios, such as checking for class membership of a model in a system. For more information on using Abstract Base Classes in Python, I advise you to read this post .StorageRoom
class StorageRoom
place the following code in the tests/serializers/test_storageroom_serializer.py
file import datetime import pytest import json from rentomatic.serializers import storageroom_serializer as srs from rentomatic.domain.storageroom import StorageRoom def test_serialize_domain_storageroom(): room = StorageRoom('f853578c-fc0f-4e65-81b8-566c5dffa35a', size=200, price=10, longitude='-0.09998975', latitude='51.75436293') expected_json = """ { "code": "f853578c-fc0f-4e65-81b8-566c5dffa35a", "size": 200, "price": 10, "longitude": -0.09998975, "latitude": 51.75436293 } """ assert json.loads(json.dumps(room, cls=srs.StorageRoomEncoder)) == json.loads(expected_json) def test_serialize_domain_storageruum_wrong_type(): with pytest.raises(TypeError): json.dumps(datetime.datetime.now(), cls=srs.StorageRoomEncoder)
rentomatic/serializers/storageroom_serializer.py
file: import json class StorageRoomEncoder(json.JSONEncoder): def default(self, o): try: to_serialize = { 'code': o.code, 'size': o.size, 'price': o.price, "latitude": o.latitude, "longitude": o.longitude, } return to_serialize except AttributeError: return super().default(o)
JSON.JSONEncoder
, we use json.dumps(room, cls = StorageRoomEncoder)
to serialize the model.StorageRoom
to JSON attributes is similar to what we use to create an object from a dictionary. Not the same, but the similarity of these two functions is present.tests/use_cases/test_storageroom_list_use_case.py
import pytest from unittest import mock from rentomatic.domain.storageroom import StorageRoom from rentomatic.use_cases import storageroom_use_cases as uc @pytest.fixture def domain_storagerooms(): storageroom_1 = StorageRoom( code='f853578c-fc0f-4e65-81b8-566c5dffa35a', size=215, price=39, longitude='-0.09998975', latitude='51.75436293', ) storageroom_2 = StorageRoom( code='fe2c3195-aeff-487a-a08f-e0bdc0ec6e9a', size=405, price=66, longitude='0.18228006', latitude='51.74640997', ) storageroom_3 = StorageRoom( code='913694c6-435a-4366-ba0d-da5334a611b2', size=56, price=60, longitude='0.27891577', latitude='51.45994069', ) storageroom_4 = StorageRoom( code='eed76e77-55c1-41ce-985d-ca49bf6c0585', size=93, price=48, longitude='0.33894476', latitude='51.39916678', ) return [storageroom_1, storageroom_2, storageroom_3, storageroom_4] def test_storageroom_list_without_parameters(domain_storagerooms): repo = mock.Mock() repo.list.return_value = domain_storagerooms storageroom_list_use_case = uc.StorageRoomListUseCase(repo) result = storageroom_list_use_case.execute() repo.list.assert_called_with() assert result == domain_storagerooms
list()
method, which returns a list of the models previously created above. Then we initialize the script with the repository and execute it, memorizing the result. The first thing we check is that the storage method was called without any parameter, and the second is the correctness of the result.rentomatic/use_cases/storageroom_use_case.py
class StorageRoomListUseCase(object): def __init__(self, repo): self.repo = repo def execute(self): return self.repo.list()
StorageRoomListRequestObject
, which can be initialized without parameters, so let's create the file tests/use_cases/test_storageroom_list_request_objects.py
and put a test for this object in it. from rentomatic.use_cases import request_objects as ro def test_build_storageroom_list_request_object_without_parameters(): req = ro.StorageRoomListRequestObject() assert bool(req) is True def test_build_file_list_request_object_from_empty_dict(): req = ro.StorageRoomListRequestObject.from_dict({}) assert bool(req) is True
StorageRoomListRequestObject
class is in the rentomatic/use_cases/request_objects.py
file and looks like this: class StorageRoomListRequestObject(object): @classmethod def from_dict(cls, adict): return StorageRoomListRequestObject() def __nonzero__(self): return True
tests/shared/test_response_object.py
from rentomatic.shared import response_object as ro def test_response_success_is_true(): assert bool(ro.ResponseSuccess()) is True
rentomatic/shared/response_object.py
file class ResponseSuccess(object): def __init__(self, value=None): self.value = value def __nonzero__(self): return True __bool__ = __nonzero__
To be continued in Part 3 .
Source: https://habr.com/ru/post/319202/
All Articles