본문 바로가기

독서찰기(讀書札記)/단위 테스트

단위 테스트 스타일

  • 출력 기반 테스트(output-based testing)
  • 상태 기반 테스트(state-based testing)
  • 통신 기반 테스트(communication-based testing)

출력 기반 테스트

테스트 대상 시스템(SUT)에 입력을 넣고 생성되는 출력을 점검하는 방식이다.

사이드 이펙트 없는 코드 선호를 강조하는 프로그래밍 방식인 함수형 프로그래밍(functional programming)에 뿌리를 두고 있다.

※ 사이드 이펙트: 메서드 시그니처에 표시되지 않은 출력

상태 기반 테스트

작업이 완료된 후 시스템 상태를 확인하는 것이다.

'상태'란 SUT, 협력자, DB, 파일 시스템 등 외부 의존성의 상태를 말한다.

통신 기반 테스트

목을 사용해 SUT와 협력자 간의 통신을 검증하는 것이다.

단위 테스트 스타일 비교

좋은 단위 테스트의 4대 요소로 비교해보자. (회귀 방지, 리팩터링 내성, 빠른 피드백, 유지 보수성)

회귀 방지, 빠른 피드백

테스트 스타일 간의 차이 없음.

리팩터링 내성

리팩터링 내성은 거짓 양성 수가 척도이다. 거짓 양성은 코드의 구현 세부 사항에 결합된 테스트에서 자주 발생한다.

출력 기반 테스트는 테스트 대상 메서드에만 결합되므로 리팩터링 내성이 가장 좋다.

상태 기반 테스트는 메서드 외에도 클래스 상태에 결합되므로 리팩터링 내성이 좋지 않다.

통신 기반 테스트리팩터링 내성이 가장 안 좋다. 목은 SUT에서 관련 의존성으로 나가는 상호작용을 모방하고 검사한다. 하지만 스텁은 SUT로 들어오는 상호작용을 모방하지만 검사하지는 않는다. 스텁과의 상호작용은 SUT가 결과물을 만들어내기 위한 것이지 SUT의 최종 결과물이 아니기 때문이다. 즉, SUT가 결과물을 만들어내기 위한 스텁 호출은 구현 세부사항에 해당한다.

유지 보수성

  • 얼마나 이해하기 어려운가? (테스트 크기와 관련)
  • 얼마나 실행하기 어려운가? (외부 의존성 개수와 관련)

출력 기반 테스트가장 유지 보수성이 좋다. 테스트가 거의 항상 짧고 간결하기 때문이다.

상태 기반 테스트유지 보수성이 안 좋다. 상태 검증은 종종 출력 검증보다 더 많은 공간을 차지하기 때문이다. 헬퍼 메서드를 사용하거나 값 객체 클래스로 변환하여 상태를 검증할 수 있으나 두 기법을 항상 쓸 수도 없을 뿐더러 관련 코드를 추가적으로 관리해줘야 한다.

통신 기반 테스트유지 보수성이 가장 안 좋다. 테스트 대역들과의 상호 작용 검증을 설정해야하기 때문이다. 목 사슬(mock chain)이 있을 때는 유지 보수성이 더 안 좋아진다.