테스트 커버리지 100%

유재희·2023년 5월 8일
0

Conference

목록 보기
2/9

[토스-슬래시 21 - 테스트 커버리지 100%]

어느정도의 테스트 커버리지가 적당할까?

  • 아마 70% 정도?

  • 다른 서버들로부터 유저의 금융 정보를 수집해 보여주는 역할
  • Spring Webflux, kotlin
  • 100% 도전


  • 커버리지 측정 시작 지점 50%, 프로덕션 코드 4000줄, 테스트코드는 2000줄
  • 84%를 달성했을때 커버리지가 낮으면 배포를 금지
  • 2달간 작성한 테스트코드 6000줄
  • 100% 달성

유지할 수 있을까??

  • 커버리지가 100이 아니면 배포가 안되니 당연히 달성

높은 테스트 커버리지의 이점

  1. 코드를 배포할때 두려움이 사라졌다.
  2. 두려움이 사라지니 더 과감한 시도가 가능해졌다. -> 거침없이 리팩토링이 가능했다.
  3. 불필요한 프로덕션 코드가 사라진다. -> 실행되지 않으면서 불필요하게 남아있는 코드들을 식별할 수 있게됐고 해당 코드를 지울 수 있음
  4. 프로덕션 코드에 대한 이해도가 높아진다. -> 테스트 코드를 작성하려면 정확히 이해해야 가능하기 때문에
  5. 점점 쉬워지는 테스트 작성 -> 테스트코드가 많아지니 참조할 수 있는 코드도 많아졌다.

1. 확고한 믿음

  • 테스트가 필요하다는 믿음이 있어야된다.
    - 고도의 정신적 노동을 자발적인 믿음없이 실행하기란 불가능하다.
    • 어떤 코드든 테스트 할 수 있다는 믿음을 가져야한다. (자기합리화 방지)

2. 시간

  • 테스트코드는 절대적인 시간이 많이 소비된다. 되도록 프로젝트 초기부터 커버리지를 높게 유지하는것이 효율적이다.

높은 커버리지를 유지하며 겪은 어려움

1. 속도

  • 보통 서버의 HTTP API를 테스트할 때 컨텍스트 로딩을 하는 경우가 많은데 많은 스프링 웹 애플리케이션 테스트 프레임워크들이 컨텍스트 로딩 없이 HTTP API를 테스트 할 수 있게 해주는 standalone 기능이 있어서 제거가 어렵지 않았다.

컨텍스트 로딩을 제거하기 어려운 경우

  • 스프링 어플리케이션이 기동 되는지를 테스트할 때는 애플리케이션 컨텍스트 로딩만 제거하는 것은 어렵기 때문에 모킹 라이브러리의 스태틱 모킹 기능을 이용해서 스프링을 모킹해서 springapplication.run()이 실행되는지만 확인

성능 프로파일링

  • MockK가 성능에 영향이 굉장히 컸다
    - MockK는 바이트 코드 조작을 위해 Byte Buddy를 이용하는데 이 Byte Buddy의 초기화가 느리고 Kotlin Reflection을 활용하는데 이 과정도 느리다.
  • 순차적인 테스트 진행으로 CPU를 제대로 활용하지 못했다.

Handlerbars JS 자바스크립트의 템플릿 엔진

  • JUnit 테스트 설정으로 테스트 병렬 실행

-> 결과 40초로 단축


진짜 어려운 테스트

  • 왼쪽 그룹 테스트들은 Mocking을 이용하면 대부분 해결이 가능

  • Kotlin Byte Code

커버리지 기준이 라인커버리지가 아닌 인스트럭션 커버리지 -> 모든 바이트 코드 인스트럭션이 커버되어야했음

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를 채

profile
몰라요

0개의 댓글