[TDD] 테스트 주도 개발 시작하기 정리 (2)

calm0_0·2023년 9월 13일
0

TDD

목록 보기
2/3

지난 시간에 이어 TDD 책을 읽고 공부한 내용을 정리해보려고 한다.

테스트 주도 개발 시작하기 - 최범균 저

테스트 코드의 구성


테스트 코드의 구성 요소

기능은 상황에 따라 결과가 달라진다. 테스트 코드는 기능을 실행하고 그 결과를 확인하므로 상황, 실행, 결과 확인(given - when - then)의 3가지 요소로 테스트를 구성할 수 있다. 어떤 상황이 주어지고, 그 상황에서 기능을 실행하고, 실행한 결과를 확인하는 3가지가 테스트 코드의 기본 골격을 이룬다.

테스트 코드의 일관성

  • 테스트는 언제 실행해도 항상 정상적으로 동작해야 한다.
  • 구현을 변경하지 않았다면 테스트는 항상 동일한 결과를 보장해야 한다.
  • 테스트는 실행 순서에 영향을 받지 않고 독립적으로 작성되어야 한다.
  • 테스트의 결과는 실행 시점이나 우연한 값에 의해 바뀌어서는 안 된다.

외부 상태와 테스트의 어려움

그런데, 파일 시스템, 데이터베이스 접근, 외부 HTTP 서버와 통신 등 테스트가 외부 요인에 의존하는 경우, 테스트 결과의 일관성을 확보하기 어렵다. 외부 상태에 따라 테스트의 성공 여부가 바뀌지 않으려면 테스트 실행 전에 외부를 원하는 상태로 만들거나 테스트 실행 후에 외부 상태를 원래대로 되돌려 놓아야 한다.

하지만, 외부 상태를 테스트에 맞게 구성하고 제어하는 것은 어렵다. 이러한 경우 대역을 사용하여 외부 요인이나 결과를 대체할 수 있다.


대역


대역이란?

대역이란 특정 객체의 동작을 흉내내는 객체이다.

대역의 종류

  • 스텁(Stub): 구현을 단순한 것으로 대체한다. 테스트에 맞게 단순히 원하는 동작을 수행한다.
  • 가짜(Fake): 제품에는 적합하지 않지만, 실제 동작하는 구현을 제공한다.
  • 스파이(Spy): 호출된 내역을 기록한다. 기록한 내용은 테스트 결과를 검증할 때 사용한다. (스텁이기도 하다)
  • 모의(Mock): 기대한 대로 상호작용하는지 행위를 검증한다. 기대한 대로 동작하지 않으면 예외를 발생할 수 있다. (모의 객체는 스텁이자 스파이도 된다)

의존 도출과 대역 사용

제어하기 힘든 외부 상황이 존재하면 다음과 같은 방법으로 의존을 도출하고 이를 대역으로 대신한다.

  • 제어하기 힘든 외부 상황을 별도 타입으로 분리
  • 테스트 코드는 별도로 분리한 타입의 대역을 생성
  • 생성한 대역을 테스트 대상의 생성자 등을 이용해서 전달
  • 대역을 이용해서 상황 구성

대역의 이점

  • 대역을 사용하면 실제 구현 없이도 다양한 상황에 대해 테스트할 수 있다.
  • 대역을 사용하면 실제 구현 없이도 실행 결과를 확인할 수 있다.
  • 즉, 대역은 의존하는 대상을 구현하지 않아도 테스트 대상을 완성할 수 있게 만들어주며 이는 대기 시간을 줄이고 개발 속도를 올리는 데 도움이 된다.

모의 객체를 과하게 사용하지 않기

모의 객체를 이용하면 대역 클래스를 만들지 않아도 되니깐 처음에는 편할 수 있다. 하지만 결과 값을 확인하는 수단으로 모의 객체를 사용하기 시작하면 결과 검증 코드가 길어지고 복잡해진다. 특히 하나의 테스트를 위해 여러 모의 객체를 사용하기 시작하면 결과 검증 코드의 복잡도는 배로 증가한다. 게다가 모의 객체는 기본적으로 메서드 호출 여부를 검증하는 수단이기 때문에 테스트 대상과 모의 객체 간의 상호 작용이 조금만 바뀌어도 테스트가 깨지기 쉽다.

이런 이유로 모의 객체의 메서드 호출 여부를 결과 검증 수단으로 사용하는 것은 주의해야 한다. 특히 DAO나 리포지토리와 같이 저장소에 대한 대역은 모의 객체를 사용하는 것보다 메모리를 이용한 가짜 구현을 사용하는 것이 테스트 코드 관리에 유리하다.

profile
공부한 내용들을 정리하는 블로그

0개의 댓글