TDD 법칙 세 가지
- 실패하는 단위 테스트를 작성할 때까지 실제 코드를 작성하지 않는다
- 컴파일은 실패하지 않으면서 실행이 실패하는 정도로만 단위 테스트를 작성한다
- 현재 실패하는 테스트를 통과할 정도로만 실제 코드를 작성한다
깨끗한 테스트 코드 유지하기
- 더러운 테스트 코드는 없느니만 못하다
- 테스트 코드가 복잡할수록 테스트 케이스를 작성하는 시간이 더 오래 걸린다
- 기능이 추가되거나 변경될 때마다 테스트 케이스를 유지/보수 하는 비용은 늘어난다
- 테스트 코드는 실제 코드 못지 않게 깨끗하게 짜야 한다
테스트는 유연성, 유지보수성, 재사용성을 제공한다
- 테스트 케이스가 있고 커버리지가 높을 수록 유연한 기능 추가/변경이 쉽다
- 아키텍처나 설계가 부실한 곳에서 더 효과있다
- 기능 변경이 되더라도 테스트 케이스만 다 통과한다면 문제가 발생하지 않기 때문
깨끗한 테스트 코드
- 깨끗한 테스트 코드를 만들기 위해서는 가독성이 중요하다
- 중복된 코드를 합치고, 테스트 케이스에 노출이 필요없는 코드는 숨긴다
- BUILD-OPERATE-CHECK 패턴이 이런 테스트 구조에 적합하다
- Build: 테스트 전 필요한 데이터를 빌드하고,
- Operate: 테스트할 API 메소드를 호출하고
- Check: 실행한 메소드의 결과가 시스템에 준영향과 DB에 준 영향을 check(확인) 하라
- 핵심은 잡다하고 세세한 코드를 다 없애 정말 필요한 자료 유형과 함수만 사용한다는 점
도메인에 특화된 테스트 언어
- 테스트 코드를 작성하며 세세한 정보와 함수를 은닉하고 테스트에 필요한 함수만 노출시키는데 이렇게 특수 API가되며 이게 테스트 언어다
- 깨끗한 테스트 코드를 만들기 위해 리팩토링을 하며 더 간결하고 표현력 있는 코드를 만들어라
이중 표준
- 테스트 API코드에 적용하는 표준은 실제 코드에 적용하는 표준과 다르다
- 실제 코드만큼 퍼포먼스를 따지지 않아도 된다.
- 테스트 환경에서 돌아가는 코드이기 때문에 요구사항이 다르기 때문이다
테스트당 assert 하나
- 최대한 하나의 테스트에서는 하나의 assert만 할 수 있도록 한다
- 하지만, 테스트를 억지로 분리하며 중복되는 코드가 많아질 경우 합치는 것도 좋다
- assert 문을 최대한 줄이는 것에 초점을 맞춘다
테스트당 개념 하나
- 코드의 중복을 고려해 assert 문을 하나로 못줄이는 경우가 많다면 생각을 바꾼다
- 테스트 함수에 하나의 개념만 테스트하라.
public void testAddMonths() {
SerialDate dl = SerialDate.createlnstance(31, 5, 2004);
SerialDate d2 = SerialDate.addMonths(1, dl);
assertEquals(30, d2.getDayDfMonth());
assertEquals(6, d2.getMonth());
assertEquals(2004, d2.getYYYY());
SerialDate d3 = SerialDate.addMonths(2, d1);
assertEquals(31, d3.getDayOfMonth());
assertEquals(7, d3.getMonth());
assertEquals(2004, d3.getYYYY());
SerialDate d4 = SerialDate.addMonths(1, SerialDate.addMonths(1, d1));
assertEquals(30, d4.getDayOfMonth());
assertEquals(7, d4.getMonth()) ;
assertEquals(2004, d4.getYYYY());
}
- 위 코드를 보면 개행순으로 3가지의 테스트를 하는데, 얼핏보면 다 날짜를 검사하는 것 같아서 같은 개념을 테스트하는거니 괜찮을 것 같지만, 사실 다 다른 개념이다
- 첫 케이스는 30일로 끝나는 한 달을 더하면 날짜는 30일이 되어야지 31이 되면 안된다
- 두 번째 케이스는 2달을 더하면 그리고 그 달이 31일로 끝나면 31일이 되어야 한다
- 마지막은 31일로 끝나는 한 달을 더하면 30일이 되어야지 31일이 되면 안되며 각각의 다른 개념을 가지고 있기에 함수를 나누는게 맞으며, 2월같은 마지막 날짜가 28일인 경우의 테스트 케이스도 채워야 한다
F.I.R.S.T
- 깨끗한 테스트가 되기 위해서는 다음 다섯 가지 규칙을 따른다
빠르게(First)
- 테스트는 빨라야 한다
- 테스트가 느리면 자주 돌리지 못하고 그 시간만큼 코드를 정리하지 못 할뿐 아니라 테스트를 자주 수행할 수 없다
독립적으로(Independent)
- 각각의 테스트가 서로 의존하면 안된다
- 한 테스트가 다음 테스트가 실행될 환경을 준비해서는 안된다
반복가능하게(Repeatable)
- 테스트는 어떤 환경에서든 반복 가능해야 한다
- 실제 환경, QA환경, 오프라인 환경 모두 가능해야 한다
- 테스트가 돌아가지 않는 환경이 있다면 핑계거리가 되며 테스트를 수행하지 못해도 넘겨야하는 상황이 생긴다
자가검증하는(Self-Validating)
- 테스트는 Boolean 값으로 결과를 내야 한다 (성공 or 실패)
- 통과했는지를 알기 위해 로그 파일이나 콘솔창을 봐야하는것은 잘못된 것이다
적시에(Timely)
- 테스트는 적시에 작성해야 한다
- 즉, 테스트하려는 실제 코드를 구현하기 직전에 구현한다
- 실제 코드를 작성 한 뒤에 테스트 코드를 작성하려 하면 테스트하기가 어려울 수도 있고, 테스트가 불가능하도록 실제 코드를 설계할 수도 있다
개인적인 감상
- TDD에 대한 중요성은 들었지만 실제 개발에 적용해본적이 없어서 이론적으로만 이해가 되었다
- 각종 강의나 유튜브 등에 예제가 있을테니 테스트를 만드는 것에 대해서 조금 더 검색해봐야 할 것 같다