Unit Testing(단위 테스트) 책을 읽고 정리한 내용입니다.
'단위 테스트를 적용해야 하는가?' 는 더이상 논쟁거리가 아니다.
우리는 '어떤 테스트가 좋은 단위 테스트인가?' 에 대해 고민하는 것이 옳다.
테스트를 많이 작성하는 것이 좋은 단위 테스트의 척도가 되지 않는다.
이 책은 좋은 단위 테스트에 대한 가이드 라인을 제공한다.
단위 테스트의 목표
흔히 단위 테스트는 더 나은 설계로 이어진다고 생각한다. 이는 사실이지만 단위 테스트의 부수적인 효과일 뿐이다.
- 단위 테스트를 하기 어렵다 > 코드 설계가 잘못 되었을 가능성이 높다.
- 단위 테스트를 하기 쉽다 > 코드 설계가 반드시 좋다는 의미는 아니다.
지속성과 확장성
단위 테스트의 진짜 목표는 소프트웨어 프로젝트의 지속 가능한 성장을 가능하게 하는 것이다.
테스트는 새로운 기능 도입 또는 리팩터링 시에 기존 기능의 작동을 확인하는 안전망 역할을 한다.
테스트가 없는 프로젝트의 경우 코드 생산성 측면에서 시작은 유리하다.
하지만 시간이 갈 수록 소프트웨어 엔트로피(시스템 내 무질서도)가 증가하고 이내 속도가 현저히 느려진다.
코드 베이스에서 무언가를 변경할 때마다 엔트로피가 높아지는 경험을 해본 적 있다. 시간이 부족하다는 이유로 코드 정리, 리팩터링 등을 하지 않고 기존 코드 베이스에 점점 덧붙여 나아갔고, 코드 베이스를 점차 신뢰할 수 없게 되었다. 이 책에서 이야기 하는 도미노 현상 (버그 수정이 더 많은 버그를 양산)을 막기 위해서 테스트 코드와 함께 코드 설계를 하는 것이 매우 중요하다고 느낀다.
테스트의 유지 비용
잘못된 테스트의 작성은 결국은 프로젝트의 침체 단계로 빠트린다.
좋은 테스트인지 여부를 판단하기 위해서 우리는 해당 테스트 코드의 가치가 유지 비용을 넘어서는지 고려할 필요가 있다.
- 기반 코드를 리팩터링할 때 테스트도 함께 리팩터링
- 각 코드 변경 시 테스트를 실행
- 테스트가 잘못된 경고를 발생시킬 경우 처리
- 기반 코드가 어떻게 동작하는지 이해하려고 할 때 테스트를 읽는데 시간을 투자
좋은 테스트 구별 방법은 4장에서 다룬다.
커버리지 지표
커버리지 지표는 좋은 부정 지표이지만 나쁜 긍정 지표이다.
커버리지가 너무 낮다면 문제가 될 수 있겠지만 높다는 것이 항상 좋은 테스트를 의미하지 않는다.
커버리지 지표를 보는 가장 좋은 방법은 지표 그 자체로 보는 것이며, 목표로 여겨서는 안된다.
- 코드 커버리지(테스트 커버리지) = 실행 코드 라인 수 / 전체 라인 수
테스트 코드가 어느정도의 코드 라인을 커버하는가에 대한 지표이다.
단순히 코드 라인을 작게 수정하는 것으로 코드 커버리지를 높일 수 있다.
- 분기 커버리지 = 통과 분기 / 전체 분기 수
코드 커버리지보다 더 정확할 수 있다. 하지만 여전히 문제점이 존재한다.
1 ) 테스트 대상 시스템의 모든 가능한 결과를 검증한다고 보장할 수 없다.
테스트 자체가 옳게 설계 되어 있는가?
커버리지 지표가 의미가 있으려면 모든 측정 지표를 검증해야 한다.
2 ) 외부 라이브러리의 코드 경로를 고려할 수 있는 코드 커버리지 지표는 없다.
외부 라이브러리의 숨겨진 코드 경로를 어떻게 모두 확인할 수 있는가? 물론 외부 라이브러리의 코드 경로를 모두 고려해서도 안된다.
즉 커버리지 지표가 좋은 테스트의 여부를 가릴 수 없다.
성공적인 테스트 슈트
1 ) 개발 주기에 통합돼 있다.
이상적 : 코드가 변경될 때 마다 아무리 작은 것이라도 실행 된다.
2 ) 코드 베이스에서 가장 중요한 부분만을 대상으로 한다.
비즈니스 로직 테스트가 시간 투자 대비 최고 이익을 낼 수 있음.
그 외) 인프라 코드, 모든 것을 하나로 묶는 코드, 데이터베이스나 서드파티 시스템과 같은 외부 서비스 및 종속성
복잡하고 중요한 알고리즘이 있으면 테스트를 많이 하는 것이 좋다.
일부 테스트는 시스템이 전체적으로 어떻게 작동하지는지 확인하는 데에 도움을 준다.
그러나 도메인 모델에 집중하는 것이 옳다.
3 ) 최소한의 유지비로 최대의 가치를 끌어 낸다.
가장 어려운 부분이자 이 책에서 말하고자 하는 핵심
다음 두 가지 능력이 바탕이 되어야 한다.
- 식별 - 가치 있는 테스트 (더 나아가 가치가 낮은 테스트) 식별하기
- 작성 - 가치 있는 테스트 작성하기 (코드 설계 기술이 요구된다)