Unit Testing

가치 있는 테스트를 위한 리팩터링

25G 2024. 3. 3. 22:11

좋은 단위 테스트 스위트의 속성을 정의

  • 개발 주기에 통합돼 있다.
  • 코드베이스 중 가장 중요한 부분만을 대상으로 한다.
  • 최소한의 유지비로 최대의 가치를 끌어낸다. 즉 가치있는 테스트를 식별하고 가치있게 작성해야한다.

리팩터링할 코드 식별하기

  • 코드 복잡도
  • 도메인 유의성
  • 클래스 또는 메서드가 가진 협력자 수
  • 협력자의 유형
  • 순환 복잡도 (1 + 분기점(if) 수)

복잡한 코드와 도메인 유의성을 갖는 코드가 단위 테스트에서 가장 이롭다. 해당 테스트가 회귀 방지에 뛰어나 지기 때문. 예로 주문 가격을 계산하는 메서드에 조건문이 없다면 순환 복잡도는 1이다. 그러나 이러한 메서드는 비즈니스적으로 중요한 기능이므로 테스트하는것이 중요하다.
협력자의 유형과 협력자 수에 따라서 테스트의 크기(유지보수성)가 결정된다.

위 조합으로 가치있는 테스트를 식별하는데에 다음과같은 경우가 유리한경우가많다.

  • 도메인 모델과 알고리즘 : 보통 복잡한 코드는 도메인 모델이지만 항상 그렇다기보단 문제 도메인과 직접적으로 관련이 없는 복잡한 알고리즘이 있을 수 있다.
  • 간단한 코드 : 협력자가 있는 경우가 거의 없고 복잡도나 도메인 유의성도 거의 없다.
  • 컨트롤러 : 이 코드는 복잡하거나 비즈니스에 중요한 작업을 하는 것이 아니라 도메인 클래스와 외부 애플리케이션 같은 다른 구성 요소의 작업을 조정
  • 지나치게 복잡한 코드: 이러한 코드는 두 가지 지표 모두 높다. 협력자가 많으며 복잡하거나 중요하다. 이에 팁이 있다면 코드가 더 중요해지거나 복잡해 질수록 협력자는 더 적어야 한다. 험블 객체 패턴을 활용해서 해당 케이스의 코드를 리팩터링하면 테스트짜기가 더 좋아진다.

추상화할 것을 테스트하기보다 추상화를 테스트하는 것이 더 쉽다

험블 객체 패턴

험블 객체 패턴은 객체들이 서로 협력하여 작업을 완료하는 디자인 패턴입니다. 이 패턴은 객체 간의 상호 작용을 명확하게 정의하여 코드를 이해하기 쉽고 유지 관리하기 쉬운 시스템을 만드는 데 도움이 된다.

  • 역할: 객체가 협력에서 수행하는 책임.
  • 책임: 역할이 수행해야 하는 특정 작업.
  • 협력: 객체들이 역할과 책임을 수행하기 위해 서로 상호 작용하는 방식.
  • 장점
    • 코드의 이해도를 높인다.
    • 유지 관리를 용이하게 한다.
    • 재사용성을 향상시킨다.
    • 결합도를 낮춘다.
  • 적용해야하는 경우
    • 객체들이 서로 협력하여 작업을 완료해야 하는 경우
    • 코드의 이해도와 유지 관리성을 높여야 하는 경우
    • 재사용성을 향상시켜야 하는 경우
    • 결합도를 낮춰야 하는 경우

항상 세가지 특성 중 최대 두가지를 가질 수 있다.

  • 외부에 대한 모든 읽기와 쓰기를 비즈니스 연산 가장자리로 밀어내기: 컨트롤러를 단순하게 유지하고 도메인 모델 테스트 유의성을 지키지만 성능이 저하된다.
  • 도메인 모델에 프로세스 외부 의존성 주입: 성능을 유지하고 컨트롤러를 단순하게 하지만 도메인 모델의 테스트 유의성이 떨어진다.
  • 의사 결정 프로세스 단계를 더 세분화하기: 성능과 도메인 모델 테스트 유의성을 지키지만, 컨트롤러의 단순함을 포기한다.

CanExcute/Excute

복잡도 증가를 완화하기 위한 대안중 하나인 패턴이다.

  • 해당 패턴은 각 Do() 메서드에 대해 CanDo()를 두고 CanDo()가 성공적으로 실행되는 것을 Do의 전제 조건으로 한다. 이 패터는 Do()전에 CanDo()를 호출하지 않을 수 없기 때문에 컨트롤러의 의사 결정을 근본적으로 제거한다.