TDD
기존의 순서인
설계 → 개발 → 테스트 (→ 설계 수정)
의 순서를
설계 → 테스트 (→설계 수정) → 개발
로 변경하여 개발하는 방법
TDD의 Cycle

- Red : 실패하는 테스트 코드 작성
- Green : (실패하는 테스트 코드 실패 시) 성공하게 하는 프로덕션 코드 작성
- Refactor : (실패하는 테스트 코드 성공 시) 테스트 코드 리팩토링 실시
FIRST 원칙
- Fast : 테스트는 빠르게 동작해 자주 돌릴 수 있어야한다.
- 테스트가 느리면 개발자가 테스트를 주저하게 된다.
- 자주 검증하지 않은 소스 코드는 버그가 발생활 확률 높아진다.
- Independent : 독립적인 테스트가 가능해야한다.
- 테스트에 필요한 데이터는 테스트 내부에서 독립적으로 사용해야 한다.
- 데이터 존재 여부를 찾는 테스트가 있는 경우엔 해당 데이터는 테스트 내부에서 생성되어야 하며, 나중에 다른데 영향 미치지않게 제거해야 한다.
- Repeatable : 어느 환경에서도 반복 가능해야하고, 매번 같은 결과를 만들어야 한다.
- 네트워크나 데이터베이스에 의존하지 않는 환경
- 환경에 의존하지 않는 테스트가 실패할 수 있는 이유는 오로지 테스트할 클래스 또는 메소드가 제대로 작동하지 않기 때문이다.
- Self-Validating : 테스트는 그 자체로 실행하여 결과 확인 가능해야함
- 테스트가 실행될 때마다 메서드 출력이 올바른지 확인하는 것은 개발자가 결정해서는 안된다.
- Timely : 비즈니스 코드가 완성되기 전에 구성하고 테스트가 가능해야 한다.
✨ Spring 에서의 TDD
- Repository → Service → Controller 순서로 개발 진행
- Repository 계층의 테스트는 인메모리 DB 기반의 통합 테스트로 진행
- Service 계층의 테스트는 Mockito를 사용해 Repository 계층을 Mock 하여 진행
- Controller 계층의 테스트는 Sprint Test의 MockMVC 를 사용하여 진행
Unit Test
주요 로직 메소드 단위의 테스트로 진행한다. Java 단위테스트 작성에는 크게 2가지 라이브러리가 사용된다.
JUnit5
: 자바 단위 테스트를 위한 테스팅 프레임워크
AssertJ
: 자바 테스트를 돕기 위해 다양한 문법을 지원하는 라이브러리
JUnit
만으로도 단위 테스트를 충분히 작성할 수 있다. 하지만 JUnit
에서 제공하는 assertEquals()
와 같은 메소드는 AssertJ
가 주는 메소드에 비해 가독성이 떨어진다. 그렇기 때문에 순수 Java 애플리케이션에서 단위 테스트를 위해 JUnit5
와 AssertJ
조합이 많이 사용된다.
좋은 테스트의 특징
💡
일반적으로 요구 사항은 계속해서 변하고, 그에 맞춰 우리의 코드 역시 변경되어야 한다.
하지만 실제 코드를 변경한다는 것은 잠재적인 버그가 발생할 수 있음을 내포하는데,
좋은 테스트 코드가 있다면 변경된 코드를 검증함으로써 이를 해결할 수 있다.
또한 실제 코드가 변경되면 테스트 코드 역시 변경이 필요할 수 있는데, 이러한 이유로 우리는 테스트 코드 역시 가독성있게 작성할 필요가 있다.
그렇기에 테스트를 작성하는 경우에는 다음을 준수하는 것이 좋다.
- 1개의 테스트 함수에 대해
assert
를 최소화 하자
- 1개의 테스트 함수는 1가지 개념 만을 테스트 하자
given/when/then 패턴
given-when-then 패턴이란 1개의 단위 테스트를 3가지 단계로 나누어 처리하는 패턴으로, 각각의 단계는 다음을 의미한다.
given
(준비): 어떠한 데이터가 준비되었을 때
when
(실행): 어떠한 함수를 실행하면
then
(검증): 어떠한 결과가 나와야 한다.