[토스-슬래시 21 - 테스트 커버리지 100%]
어느정도의 테스트 커버리지가 적당할까?
- 다른 서버들로부터 유저의 금융 정보를 수집해 보여주는 역할
- Spring Webflux, kotlin
- 100% 도전
- 커버리지 측정 시작 지점 50%, 프로덕션 코드 4000줄, 테스트코드는 2000줄
- 84%를 달성했을때 커버리지가 낮으면 배포를 금지
- 2달간 작성한 테스트코드 6000줄
- 100% 달성
유지할 수 있을까??
- 커버리지가 100이 아니면 배포가 안되니 당연히 달성
높은 테스트 커버리지의 이점
- 코드를 배포할때 두려움이 사라졌다.
- 두려움이 사라지니 더 과감한 시도가 가능해졌다. -> 거침없이 리팩토링이 가능했다.
- 불필요한 프로덕션 코드가 사라진다. -> 실행되지 않으면서 불필요하게 남아있는 코드들을 식별할 수 있게됐고 해당 코드를 지울 수 있음
- 프로덕션 코드에 대한 이해도가 높아진다. -> 테스트 코드를 작성하려면 정확히 이해해야 가능하기 때문에
- 점점 쉬워지는 테스트 작성 -> 테스트코드가 많아지니 참조할 수 있는 코드도 많아졌다.
1. 확고한 믿음
- 테스트가 필요하다는 믿음이 있어야된다.
- 고도의 정신적 노동을 자발적인 믿음없이 실행하기란 불가능하다.
- 어떤 코드든 테스트 할 수 있다는 믿음을 가져야한다. (자기합리화 방지)
2. 시간
- 테스트코드는 절대적인 시간이 많이 소비된다. 되도록 프로젝트 초기부터 커버리지를 높게 유지하는것이 효율적이다.
높은 커버리지를 유지하며 겪은 어려움
1. 속도
- 보통 서버의 HTTP API를 테스트할 때 컨텍스트 로딩을 하는 경우가 많은데 많은 스프링 웹 애플리케이션 테스트 프레임워크들이 컨텍스트 로딩 없이 HTTP API를 테스트 할 수 있게 해주는 standalone 기능이 있어서 제거가 어렵지 않았다.
컨텍스트 로딩을 제거하기 어려운 경우
- 스프링 어플리케이션이 기동 되는지를 테스트할 때는 애플리케이션 컨텍스트 로딩만 제거하는 것은 어렵기 때문에 모킹 라이브러리의 스태틱 모킹 기능을 이용해서 스프링을 모킹해서 springapplication.run()이 실행되는지만 확인
성능 프로파일링
- MockK가 성능에 영향이 굉장히 컸다
- MockK는 바이트 코드 조작을 위해 Byte Buddy를 이용하는데 이 Byte Buddy의 초기화가 느리고 Kotlin Reflection을 활용하는데 이 과정도 느리다.
- 순차적인 테스트 진행으로 CPU를 제대로 활용하지 못했다.
Handlerbars JS 자바스크립트의 템플릿 엔진
-> 결과 40초로 단축
진짜 어려운 테스트
커버리지 기준이 라인커버리지가 아닌 인스트럭션 커버리지 -> 모든 바이트 코드 인스트럭션이 커버되어야했음
counter : 커버리지 측정의 최소 단위를 나타냅니다.
이 때 측정은 java byte code가 실행된 것을 기준으로 counting됩니다.
counter의 종류는 CLASS, METHOD, LINE, BRANCH 등이 있습니다.
CLASS : 클래스 내부 메소드가 한번이라도 실행된다면 실행된 것으로 간주됩니다.
METHOD : 클래스와 마찬가지로 METHOD가 한번이라도 실행되면 실행된 것으로 간주됩니다.
LINE : 한 라인이라도 실행되었다면 측정이 됩니다.
소스 코드의 포맷에 영향을 받습니다.
BRANCH : if, switch 구문에 대한 커버리지 측정을 합니다.
INSTRUCTION : 자코코의 가장 작은 측정 단위입니다.
소스 코드 포맷에 영향을 받지 않습니다!
- nullable한 객체에 nonnull필드가 존재할때 이 getter에 대한 테스트 -> person이 null일경우 아무개 반환 -> elvis operator
- 테스트를 작성했는데 모든 케이스가 커버되지 않음
- 컴파일된 바이트 코드를 자바로 역컴파일 해보니 name이 null일 경우 분기문이 작성되어있음 즉 코틀린의 nonnull은 코틀린 레벨에서만 nonnull이 확정이지 JVM레벨에서는 아니다. -> 결국 elvis operator 대신 if문으로 처리헸다. (테스트를 위해 프로덕션 코드가 바뀐 경우)
진짜 진짜 진짜 테스트가 불가능한 케이스가 나올 수 있다.
- 커버리지 검사 도구가 특정 파일을 제외시키는 기능을 제공 (??)
100%가 99%보다 단순한 커버리지인 이유
100%를 넘어서
1. 테스트 코드를 잘못 작성하는 경우
- 누군가 sum 함수의 연산자를 빼기로 바꾸면? 테스트 커버리지 100%유지, 버그발생
예방법
- Mutation testing : 프로덕션 코드를 무작위로 변경해보는것.
- pitest.org (Mutation testing을 도와주는 도구)
- 성능이 너무 구려진다.
2. 요구사항을 오해하여 테스트코드를 잘못 작성한경우
3. 컴포넌트간 협업 실패
- Consumer가 요구사항을 Machine-Readable하게 작성하면 Provider가 요구사항을 만족하는지 테스트하는 기법
- 테스트 도구로 Pact를 채