2023.02.08 - [디자인패턴] - 저장소 패턴을 알아보자 - 1에 이어 두 번째
기능을 구현할 때 항상 테스트부터 작성하자. 이 테스트는 코드(저장소)가 데이터베이스와 제대로 연동하는지 검사하기 때문에 아마 통합 테스트로 분류할 수 있다.
#객체를 저장하는 저장소 테스트(test_repository.py)
def test_repository_can_save_a_batch(session):
batch = model.Batch('batch1', 'RUSTY-SOAPDISH', 100, eta=None)
repo = repository.SqlAlchemyRepostiory(session)
repo.add(batch) # 여기서 테스트하는 메서드는 repo.add() 이다.
session.commit() # 저장소 밖에서 .commit()을 반복 수행해야 하며 이를 저장소를 호출하는 쪽의 책임으로 한다. 이런 방식에는 장단점이 있다.
rows = list(session.execute(
'SELECT reference, sku, _purchased_quantity, eta FROM "batches"' # SQL 문을 사용해 저장된 데이터가 맞는지 검증한다.
))
assert rows == [('batch1', 'RUSTY-SOAPDISH', 100, None)]
다음 테스트는 배치와 할당을 읽어오는 기능을 검사한다. 이 테스트는 좀 더 복잡하다.
# 복잡한 객체를 읽는 기능에 대한 저장소 테스트(test_repository.py)
def insert_order_line(session):
session.execute( # 이 테스트는 읽기 기능을 검사한다. 그래서 이 SQL문은 repo.get()이 읽을 데이터를 준비한다.
"INSERT INTO order_lines (orderid, sku, qty)"
' VALUES ("order1", "GENERIC-SOFA", 12)'
)
[[orderline_id]] = session.execute(
"SELECT id FROM order_lines WHERE orderid=:orderid AND sku=:sku",
dict(orderid="order1", sku="GENERIC-SOFA"),
)
return orderline_id
def insert_batch(session, batch_id):
...
def test_repository_can_retrieve_a_batch_with_allocations(session):
orderline_id = insert_order_line(session)
batch1_id = insert_batch(session, "batch1")
insert_batch(session, "batch2")
insert_allocation(session, orderline_id, batch1_id) # 이 부분이 테스트에서 검증이 이루어지는 부분이다. 첫 번째 assrt ==는 타임이 일치하는지 검사하고, 참조가 같은지 검사한다.
repo = repository.SqlAlchemyRepository(session)
retrieved = repo.get("batch1")
expected = model.Batch("batch1", "GENERIC-SOFA", 100, eta=None)
assert retrieved == expected # Batch.__eq__ only compares reference
assert retrieved.sku == expected.sku
assert retrieved._purchased_quantity == expected._purchased_quantity
assert retrieved._allocations == { # 명시적으로 ._allocations 등의 주요 속성이 같은지 검색한다.
model.OrderLine("order1", "GENERIC-SOFA", 12),
}
이러한 저장소 패턴은 테스트를 작성할 때 큰 이점을 보여준다. 테스트에서 가짜 저장소를 통해 실제 데이터베이스를 이용하지 않아도 간단한 테스트를 작성할 수 있기 때문이다.
파이썬에서 포트는 무엇이고, 어댑터란 무엇인가
여기서는 주로 의존성 역전에 대해 다룬다. 포트와 어댑터는 객체 지향 세계에서 나온 용어이다. 여기서 포트는 애플리케이션과 추상화하려는 대상 사이의 인터페이스이며, 어댑터는 이 인터페이스나 추상화가 뒤에 있는 구현이라는 정의를 채택한다.
파이썬은 인터페이스라는 요소 자체를 제공하지는 않는다. 따라서 어댑터를 식별하기는 쉽지만 포트를 정의하기는 어렵다. 추상 기반 클래스를 사용한다면 포트다. 추상 기반 클래스를 사용하지 않는다면 포트는 어댑터가 준수하고 애플리케이션이 (모든 어댑터가 지킬 것으로) 기대하는 덕 타입(사용 중인 함수와 메서드 이름과 인수 이름과 타입) 일뿐이다.
구체적으로 여기서는 AbstractRepository는 포트고, SqlAlchemyRepository와 FakeRepository는 어댑터다.
'디자인패턴' 카테고리의 다른 글
저장소 패턴을 알아보자 - 1 (0) | 2023.02.08 |
---|