이 정리는 자바와 JUnit을 활용한 실용주의 단위 테스트를 보고 개인적으로 정리한 글 입니다
피해야 하는 테스트
- 테스트를 사용하는 사람에게 어떤 정보도 주지 못하는 테스트
- 산발적으로 실패하는 테스트
- 어떤 가치도 증명하지 못하는 테스트
- 실행하는 데 오래 걸리는 테스트
- 코드를 충분히 커버하지 못하는 테스트
- 구현과 강하게 결합되어 있는 테사ㅡ트. 따라서 작은 변화에도 다수의 테스트가 깨진다
- 수많은 설정 고리로 점프하는 난해한 테스트
[F]IRST -> Fast : 빠르다
빠른 테스트는 코드만 실행한다 (DB 같은 외부 시스템 접근 X) 느린 테스트는 데이터베이스, 파일 입출력, 네트워크 호출처럼 필요한 외부 자원을 다루는 코드를 호출
F[I]RST -> Isolate : 고립시키다
데이터베이스에 의존해야 하는 테스트는 데이터베이스가 올바른 데이터를 가지고 있는지 확인해야 한다 데이터 소스를 공유한다면 테스트를 깨트리는 범위 밖에 있는 상황도 생각해야 한다 생성된 데이터를 재사용하는 방식으로 테스트 순서를 조작하여 전체 테스트의 실행 속도를 높일 수 있다 하지만 이를 통해 의존성의 악순환이 발생하고, 일이 잘못되면 테스트 실패 시 앞선 이벤트의 긴 사슬을 따라가야 하기 때문에 긴 시간을 소모할 수도 있다
다른 단위 테스트에 의존하지 않는 것으로 해결하자 (순서 및 시간에 관계 없이 실행할 수 있어야 한다)
테스트 메서드가 하나 이상의 이유로 깨진다면 테스트를 분할하는 것도 고려해보자
FI[R]ST -> Repeatable : 반복 가능해야 한다
반복 가능한 테스트 ?
실행할 때마다 결과가 같아야 한다 따라서 반복 가능한 테스트를 만들기 위해서는 직접 ‘통제’할 수 없는 외부 환경에 있는 항목들과 격리시켜야 한다
하지만, 시스템은 불가피하게 통제할 수 없는 요소와 상호 작용해야 할 수도 있다
ex) 현재 시간을 다루는 시스템
이럴 때를 대비하여 목 객체를 사용하자
1
2
3
4
5
Instant now = new Date().toInstant();
//
//
//
object.setCreateTimestamp(clock.instant());
FIR[S]T -> Self-validating : 스스로 검증 가능한
테스트 결과를 수동으로 검증하는 것은 시간 소모적인 절차고 리스크가 늘어난다 (멍해지기 쉽고, 중요한 순간을 놓칠 수 있다) 테스트는 스스로 검증 가능할 뿐만 아니라 준비할 수도 있어야 한다 테스트를 실행하기 전에 수동으로 준비 단계를 만드는 어리석은 짓이다 테스트에 필요한 어떤 설정 단계든 자동화를 해야 한다
FIRS[T] -> Timely : 적시의
단위 테스트를 건너뛰거나 미루기 쉽다 하지만 이렇게 미룰수록 불쾌한 결함이 늘어날 수 있다 또한 테스트 없이 소스 코드 저장소에 넣으면 그것을 되돌려서 테스트를 작성하기에는 더욱 더 힘들어 진다
옛날 코드에 대한 테스트는 시간 낭비가 될 수 있다 코드에 큰 결함이 없고 당장 변경할 예정이 없다면 노력 대비 보상은 거의 받지 못할 것이다 이 노력을 좀 더 말썽 부리거나 역동적인 부분에 사용하는 것이 낫다