🌱 들어가기 전
이번 포스팅에서는 실패하는 테스트 코드에 대한 분석과 개발자로서 테스트 코드를 짤 때 가져야하는 관점에 대해 알아보자.
- 김우근님의 'Java/Spring 테스트를 추가하고 싶은 개발자들의 오답노트'를 공부하고 정리한 글입니다. ✏️
🌱 테스트 코드를 넣게되는 시나리오
서비스 성장세 → 인력 충원 → 개발 속도 정체기 발생
💭 왜 성장할수록 개발 속도에 정체기가 발생할까? 무엇이 문제일까?
개발자들이 배포를 두려워한다.
즉, 문제는 회귀 버그를 두려워하는 것이다.
🧐 회귀 버그란?
💡 회귀 버그(Regression)란, 프로그램 변경 중 이전에 제대로 작동하던 소프트웨어 기능에 문제가 생기는 것이다.
💭 문제 해결
테스트를 도입한다.
💭 테스트를 도입한 후, 어떤 상황을 맞이하게 될까?
작업자들은 가시적 성과를 위해 커버리지를 체크한다. 커버리지를 위한 테스트를 짜기시작한다. 이렇게 문제가 발생하는 것이다.
ex. 간단한 서비스 로직에 비해 장황한 테스트코드를 만들고 있는 자신을 발견한다. 이상하다 느끼지만, 커버리지를 위해 진행한다..
🌱 테스트 코드에서 발생하는 문제
- 요령없이 짠 옛날 코드
- 비결정적 테스트
🧐 비결정적 테스트란?
💡 돌릴 때마다 결과가 다른 테스트이다.
데이터베이스와 같은 공유 자원을 사용하는 테스트는 실행 순서에 따라 성공, 실패 여부가 결정되는 비결정적인(non-deterministic) 테스트가 될 수 있다. → 테스트 실패시, 버그가 원인인지, 비결정적 동작이 원인인지 알기 힘들다. → 따라서 테스트는 실행 순서에 상관 없이 독립적으로, 결정적(deterministic)으로 실행되어야한다.
테스트 격리는 공유 자원을 사용하는 여러 테스트끼리 격리하여 서로 영향을 주고 받지 못하게 하는 기법이다. 특히 데이터베이스를 사용하는 객체를 테스트할 때 테스트 격리가 필요하다.
🌱 앞에서 본 시나리오의 문제
설계 개선 없이, 커버리지만 보고 억지로 레거시 코드에 테스트를 넣었다.
- 레거시 코드에 테스트를 넣는게 TDD가 아니다!
- 레거시에 테스트를 넣으려면, 코드 개선이 필요하다.
- 커버리지에 집착하면 안된다.
코드짜다보면 테스트가 필요없는 부분이 있을 수 있다. 테스트를 추가했을 때 얻을 수 있는 효용성을 생각하자!
커버리지 자체가 목적이 되면 테스트를 통해 얻을 수 있는 장점을 놓칠 수 있다.
💭 테스트 목적
- 회귀 버그 방지
- 유연한 설계로 개선
: 테스트를 쉽게 만들어준다. 결과적으로 테스트를 결정적이게 만들어준다.
즉 앞의 시나리오는 회귀 버그 방지에만 초점을 두었다. 설계가 뻣뻣한 것이다.
- 뻣뻣한 설계: Spring이나 JPA에 의존적인 것
테스트 짤 때에 외부 시스템에 의존되는 상황을 피하라는 신호가 보이면, 개발자는 이를 캐치해서 설계를 진화시켜야한다. mokito를 써서 해결하는 방식만 고집하기보다, 설계 개선을 고민하자.
테스트와 설계는 긴밀한 관계를 갖고있다. 테스트를 고민하면 설계가 개선되고, 설계를 고민하면 테스트가 쉬워진다.
🌱 결론
커버리지를 올리기위한 mock 프레임워크 사용법만 고민할게 아니라, 왜 테스트를 해야하며 어떻게 테스트 해야하는지 고민해야한다.
테스트를 통해 얻을 수 있는 핵심가치에 집중하자!
TDD를 논하기 전에, 테스트가 가능한 구조로 변경되어야 한다.
(소형차를 기차로 변경한다. 소형차와 비교해서 기차는 확장성을 지니고있다.)
'Back-End > Test Code' 카테고리의 다른 글
[테스트 코드와 설계] 프로젝트 Test Code 작성과 문제 해결 (0) | 2024.09.04 |
---|---|
[테스트 코드와 설계] 빌더 패턴과 엔티티, 그리고 테스트에 대한 조언 (0) | 2024.09.04 |
[테스트 코드와 설계] 의존성 주입과 의존성 역전을 활용하여 테스트 가능성 높이기 (0) | 2024.09.03 |
[테스트 코드와 설계] 테스트에 대한 개발자의 고민과 이론 및 개념 (1) | 2024.09.03 |
[테스트 코드와 설계] 테스트 코드 작성과 리팩토링 (0) | 2024.08.30 |