테스트 주도 개발 시작하기 | 최범균 - 교보문고
테스트 주도 개발 시작하기 | 작동하는 깔끔한 코드를 만드는 데 필요한 습관 - JUnit 5를 이용한 테스트 주도 개발 안내 - 테스트 작성과 설계를 위한 대역 - 테스트 가능한 설계 방법 안내 - 유지
product.kyobobook.co.kr
작년부터 테스트 코드에 관심이 생기기 시작했는데 이번 프로젝트에서 본격적으로 써보기 전에 제대로 된 서적 하나는 읽어야겠다 싶어서 주변 개발자 분께 추천을 받아서 읽게 된 책이다. 이 책을 사기 전에 <단위 테스트>라는 책의 두 챕터 정도를 먼저 읽었는데 그때는 모호했던 개념들이 이 책을 읽고 나서 다시 보니 조금 더 정리가 됐다.
TDD를 썼을 때 개발자는 어떤 이점을 경험할 수 있는지와 테스트의 범위 그리고 테스트 대역 객체들을 어떨 때 써야하는지에 대해 배우고 싶다면 이 책을 보면 좋을 것 같다. 그리고 유지 보수하기 좋은 테스트 코드와 좋지 않은 예도 보여주기 때문에 테스트 코드를 처음 작성하는 사람들도 이해하기 쉬울 것 같다.
TDD란 무엇인가
기능을 검증하는 테스트 코드를 먼저 작성하고 테스트를 통과시키기 위해 개발을 진행하는 방법이다.
TDD Cycle (Red - Green - Refactor의 반복)
테스트를 먼저 작성하고 테스트를 통과시킬 만큼 코드를 작성하고 리팩토링으로 마무리하는 과정을 반복한다.
- 기능을 검증하는 테스트를 먼저 작성한다.
- 작성한 테스트를 통과하지 못하면 테스트를 통과할 만큼만 코드를 작성한다.
- 테스트를 통과한 뒤에 개선할 코드가 있다면 리팩토링한다.
- 다시 테스트를 실행해서 기존 기능이 그대로 동작하는지 확인한다.
- 1-4를 반복하여 기능을 완성한다.
장점
- 개발 과정에서 지속적으로 코드 정리를 하기 때문에 코드 품질이 급격히 나빠지지 않게 막을 수 있으므로 유지보수 비용을 낮춘다.
- 새로운 코드를 추가하거나 기존 코드를 수정할 때 테스트를 이용해서 제대로 동작하는지 바로 확인할 수 있으므로 잘못된 코드가 배포되는 것을 방지한다.
대역의 필요성
테스트를 작성하다 보면 외부 요인이 필요한 시점이 있다.
- 테스트 대상에서 파일 시스템 사용
- 테스트 대상에서 DB로부터 데이터를 조회하거나 데이터를 추가
- 테스트 대상에서 외부의 HTTP 서버와 통신
이럴 때 대역 클래스를 만들어서 실제 외부 API와 연동하지 않고도 테스트할 수 있게 할 수 있다.
대역의 종류
대역 종류 | 설명 |
스텁(Stub) | 구현을 단순한 것으로 대체한다. 테스트에 맞게 단순히 원하는 동작을 수행한다. StubCardNumberValidator가 스텁 대역에 해당한다. |
가짜(Fake) | 제품에는 적합하지 않지만, 실제 동작하는 구현을 제공한다. DB 대신에 메모리를 이용해서 구현한 MemoryAutoDebitInfoRepository가 가짜 대역에 해당한다. |
스파이(Spy) | 호출된 내역을 기록한다. 기록한 내용은 테스트 결과를 검증할 때 사용한다. 스텁이기도 하다. |
모의(Mock) | 기대한 대로 상호작용하는지 행위를 검증한다. 기대한 대로 동작하지 않으면 익셉션을 발생할 수 있다. 모의 객체를 스텁이자 스파이도 된다. |
주의할 점
모의 객체를 과하게 사용하지 말자.
- 모의 객체를 이용하면 대역 클래스를 만들지 않아도 되니까 처음에는 편할 수 있다. 하지만 결과 값을 확인하는 수단으로 모의 객체를 사용하기 시작하면 결과 검증 코드가 길어지고 복잡해진다.
- 모의 객체는 기본적으로 메서드 호출 여부를 검증하는 수단이기 때문에 테스트 대상과 모의 객체 간의 상호 작용이 조금만 바뀌어도 테스트가 깨지기 쉽다.
- 모의 객체의 메서드 호출 여부를 결과 검증 수단으로 사용하는 것은 주의해야 한다.
- 특히 DAO나 리포지토리와 같이 저장소에 대한 대역은 모의 객체를 사용하는 것보다 메모리를 이용한 가짜 구현을 사용하는 것이 테스트 코드 관리에 유리하다.
테스트 범위
단위 테스트
- 단위 테스트는 개별 코드나 컴포넌트가 기대한대로 동작하는지 확인한다.
- 한 클래스나 한 메서드와 같은 작은 범위를 테스트한다. 일부 의존 대상은 스텁이나 모의 객체 등을 이용해서 대역으로 대체한다.
통합 테스트
- 시스템의 각 구성 요소가 올바르게 연동되는지 확인한다.
- 기능 테스트는 앱을 통해 가입 기능을 테스트한다면 통합 테스트는 서버의 회원 가입 코드를 직접 테스트하는 식이다.
- 회원 가입 관련된 서비스 클래스, DAO 인터페이스, SQL 쿼리를 구현했다면 이들을 통합한 회원 가입 서비스 클래스에 대한 테스트가 통합 테스트 예가 될 수 있다.
- 스프링 프레임워크나 마이바티스 설정이 올바른지, SQL 쿼리가 맞는지, DB 트랜잭션이 잘 동작하는지 등을 검증할 수 있다.
기능 테스트
- 기능 테스트는 사용자 입장에서 시스템이 제공하는 기능이 올바르게 동작하는지 확인한다.
- 사용자가 직접 사용하는 웹 브라우저나 모바일 앱부터 시작해서 데이터베이스나 외부 서비스에 이르기까지 모든 구성 요소를 하나로 엮어서 진행한다.
'노트 > Review' 카테고리의 다른 글
[서적] 개발자 원칙 | 박성철 외 8명 (0) | 2023.06.26 |
---|---|
[서적] 객체지향의 사실과 오해 | 조영호 (2) | 2023.06.20 |
[서적] 실습과 그림으로 배우는 리눅스 구조 | 다케우치 사토루 (0) | 2023.01.18 |
[서적] 애자일 회고 | 에스더 더비‧다이애나 라센 (0) | 2023.01.08 |
[서적] 도메인 주도 개발 시작하기 | 최범균 (1) | 2023.01.07 |