들어가며

단위 테스트와 기반 코드를 서로 얽혀있다. 따라서 코드 베이스에 노력을 기울이지 않고서는 가치 있는 테스트를 만들 수 없다. 이번 장에서는 코드의 네 가지 유형을 살펴보고 어떤 유형이 테스트하기 적합한지 알아보자.

 

코드의 네 가지 유형

모든 제품 코드는 2차원으로 분류할 수 있다.

  • 복잡도 또는 도메인 유의성
    • 코드의 복잡도는 코드 내 의사 결정(분기) 지점 수로 정의한다. 이 숫자가 클수록 복잡도는 더 높아진다.
    • 도메인 유의성은 코드가 프로젝트의 문제 도메인에 대해 얼마나 의미 있는지를 나타낸다. 일반적으로 도메인 계층의 모든 코드는 최종 사용자의 목표와 직접적인 연관성이 있으므로 도메인 유의성이 높다.
  • 협력자 수
    • 협력자는 가변 의존성이거나 프로세스 외부 의존성이다.
    • 협력자가 많은 코드는 테스트 비용이 많이 든다. 상호 작용 확인을 위한 코드(의존 객체 세팅, 목 등)가 필요하기 때문이다.

 

 

코드 복잡도/도메인 유의성과 협력자를 고려하면 제품 코드를 네 가지로 구분할 수 있다.

  1. 도메인 모델과 알고리즘
    • 보통 복잡한 모델은 도메인 모델이다. 그러나 문제 도메인과 직접적으로 관련이 없는 복잡한 알고리즘이 있는 경우가 있다.
    • 단위 테스트에 가장 적합한 유형이다.
  2. 간단한 코드
    • getter, setter와 같은 단순한 로직이나 매개 변수가 없는 생성자 등이 해당된다.
    • 테스트할 필요가 없다.
  3. 컨트롤러
    • 여기서는 복잡하거나 비즈니스에 중요한 작업을 하지 않는다. 도메인 클래스와 외부 애플리케이션 같은 다른 구성 요소의 작업을 조정하는 역할만 수행한다.
    • application 영역에 해당되며, 통합 테스트에 적합하다.
  4. 지나치게 복잡한 코드
    • 덩치가 큰 서비스 로직과 같이, 협력자가 많으며 복잡하거나 중요하다.
    • 협력자가 많아 단위 테스트가 어렵기 때문에 도메인 모델/알고리즘과 컨트롤러라는 두 부분으로 나누어야 한다.

 

컨트롤러(application 서비스)에서 조건부 로직 처리

비즈니스 로직과 오케스트레이션의 분리는 다음과 같이 비즈니스 연산이 세 단계로 있을 때 가장 효과적이다.

  • db에서 데이터 조회
  • 비즈니스 로직 실행
  • db에 데이터 저장

 

하지만 비즈니스 로직 중간에 외부에서 추가 데이터를 조회하는 등의 작업이 있다면 어떻게 할까? 크게 세 가지 방법이 있다.

  1. 외부에 대한 모든 읽기와 쓰기를 비즈니스 연산 가장자리로 밀어내기 : 컨트롤러 단순화를 유지하고 프로세스 외부 의존성과 도메인 모델을 분리할 수 있다. 하지만 필요 없는 경우에도 외부 의존성을 호출하기 때문에 성능이 저하된다.
  2. 도메인 모델에 프로세스 외부 의존성을 주입하기 : 성능을 유지하면서 컨트롤러를 단순화할 수 있다. 하지만 도메인 모델의 테스트 유의성이 떨어진다.
  3. 의사 결정 프로세스 단계를 더 세분화 하기 : 성능과 도메인 모델 테스트 유의성에 도움을 준다. 하지만 컨트롤러에 의사 결정 지점이 생기므로 복잡해진다.

 

컨트롤러 단순성, 도메일 모델 테스트 유의성, 성능이라는 세 가지 특성을 모두 충족시키는 해법은 없다.

 

대부분의 소프트웨어 프로젝트는 성능이 매우 중요하다. 도메인 모델에 외부 의존성을 주입하면 테스트와 유지보수가 어려워진다. 따라서 의사 결정 프로세스 단계를 더 세분화하는 방법만 남는다. 컨트롤러가 복잡해지긴 하지만 이를 완화하는 방법이 있다.

 

컨트롤러 복잡도를 완화하는 방법

  1. canExecute/execute 패턴 사용 : 복잡한 코드를 최대한 도메인 모델에 집어 넣고, 애플리케이션 서비스에서는 canExecute가 true일 때만 실행하도록 단순화 할 수 있다.
  2. 도메인 이벤트 사용 : 비즈니스 로직 중간에 외부 시스템에 알려야 하는 상황이 있을 수 있다. 도메인 이벤트를 사용하면 비즈니스 로직에서는 그저 이벤트를 던지기만 하고, 애플리케이션 서비스에서 일괄적으로 처리하도록 할 수 있다. 자세한 내용은 다른 페이지에서 다루도록 하겠다.

개인적인 견해로 코틀린에서는 파라미터로 함수를 넘기는게 가능하기 때문에, 해당 방법을 사용하면 외부 의존성과 의사 결정이 효과적으로 분리가 가능하다고 생각한다.

'테스트' 카테고리의 다른 글

목 사용 팁  (0) 2023.09.18
단위/통합 테스트에서의 데이터베이스  (0) 2023.09.18
단위 테스트의 세 가지 스타일  (0) 2023.09.17
테스트 대역(Test Double)이란?  (0) 2023.09.17
좋은 단위 테스트의 4대 요소  (0) 2023.09.17

+ Recent posts