세미나

SLASH 21 컨퍼런스

향찡 2021. 5. 1. 16:38

이응준, 테스트 커버리지 100% 

  • 테스트 커버리지는 얼마만큼 이 적당할까? 70%?
  • 클린 코더를 읽다가 테스트 커버리지 100%를 요구
    • -> 말도 안 되는 것 같음, 테스트 어려운 코드도 존재하기 때문에

새로운 프로젝트에 테스트 커버리지 100% 도전

  • 의외로 가능 (인스트럭션 기준으로 커버리지 100% 기록)
  • 테스트 커버리지가 떨어지면 빌드가 안되게 설정
  • 프로덕션 코드는 4천 라인, 테스트 코드 2천 라인(50%)
  • 테스트 코드 6천 라인까지 도달 (100%, 23% 커밋이 테스트 코드)

계속 유지할 수 있을까?

  • 다행히 유지가 가능했다.

장점들

  • 자신 있게 배포를 할 수 있게 되었다.
  • 테스트 커버리지가 100% 된 이후 거침없이 리팩토링이 가능, 마스터 브랜치에 걱정 없이 머지
  • 불필요한 프로덕션 코드가 사라진다
  • 프로덕션 코드에 대한 이해도 상승
  • 점점 쉬워지는 테스트 작성(기존 테스트 코드 참고)

테스트 커버리지를 높이기 위해 필요한 것들

  • 믿음, 시간이 많이 소요

필요하지 않은 것들

  • 의지 : 편한 길을 택하려는 유혹,
  • 도구를 이용 Gradle의 Jacoco의 빌드 실패 이용

2가지 어려움

1. 느려지는 테스트 : 400개 테스트 시 1분 초과(생산성 저하)

느려지는 원인 : 스프링 애플리케이션 컨텍스트 로딩

해결

  • 스프링 애플리케이션 컨텍스트 로딩 제거, 모킹 라이브러리 이용
  • 1-1 다시 느려지는 테스트 : 1600개 테스트 시 1분 초과
  • intelliJ이 프로파일러인 async-profiler 이용하여 성능 프로파일링 그 결과 아래 원인들 도출
  • 느려지는 원인 : SLFJ4 초기화, Jackson ObjectMapper() 생성, Handlebars 컴파일, Byte Buddy 초기화, 코틀린 리플렉션 모듈 초기화, MockK, 테스트의 순차적 실행(CPU를 충분히 활용하지 못함) 

해결

  • 불필요한 로깅 설정 제거
  • Jackson을 Gson으로 교체
  • handlebars 캐시 적용
  • ByteBuddy테스트에서 사용 중단
  • 코틀린 리플렉션 모듈 초기화의 isSubclassOf 함수 호출 제거
  • MockK 필수적이지 않으면 모두 제거
  • 테스트를 클래스 단위로 병렬 실행
  • 다시 40초 미만으로 실행됨, 노트북 교체 후 6초대

2. 진짜 어려운 테스트

  • 어려울 거라 생각했던 테스트 
  • DB테스트
  • 네트워크 테스트
  • 프레임워크 테스트
  • 랜덤 테스트
  • 시간에 의존적인 테스트
  • -> mocking으로 어떻게든 테스트 가능

진짜 어려운 테스트는?

  • 코틀린이 생성해낸 바이트 코드 테스트하기

100% 규칙

  • 새로 추가한 코드가 조금이라도 커버되지 않으면 언제나 실패
  • 커버리지 리포트를 보고 빠뜨린 곳을 알 수 있다.

99% 규칙

  • 운 좋게 넘어갈 수도, 억울하게 실패할 수도 있다

100%를 넘어서

  • 그래도 버그는 있다.
  • 1. 테스트를 잘못 작성하는 경우
    • 테스트 케이스가 부족할 때 -> Mutation Testing / pitest.org (굉장히 느리므로, 중요한 로직에만 적용하는 것이 좋다.)
  • 2. 요구 사항에 오해가 생긴 경우
    • 테스트로 스펙 문서 만들기 : Cucumber의 스펙 문서 생성 -> 만족스럽지 못함 -> Junit5의 TestExecutionListener를 이용하여 스펙문서 생성 프로그램 개발
  • 3. 컴포넌트 간 협업이 실패할 경우
    • 다른 서버와 협업하는 경우, Consumer Driven Contracts기법을 이용
    • Spring Cloud Contract와 Pact 중 Pact를 이용하기로 결정

결론

  • 테스트 커버리지는 얼마든지 높일 수 있다.
  • 테스트 커버리지가 낮으면 빌드 실패하게 하자.
  • 테스트는 빨라야 한다.
  • 커버리지가 100%라도 버그는 있다.

이항령,  토스 서비스를 구성하는 서버 기술

1. 토스 서비스를 구성하는 서버 기술들

  • 2개의 데이터 센터를 active-active, AWS 등등....
  • 최근 개발 소스는 코틀린 이용

2. 데이터 센터 트래픽 조절

  • 서비스 카나리 배포를 데이터 센터에 적용

3. K8S + Istio

  • DC/OS에서 K8S로 마이그레이션
  • 높은 Observability
  • application concern을 infrastructure concern으로 변경하기 에는 힘든 부분도 존재
  • 1% Canary 가능
  • Failure Injection Test / Squeeze Test
  • Failure Injection Test : 특정 조건에 맞는 요청의 경우 실패, 응답을 늦게 하도록 만들어 서비스에서 실패에 대한 처리가 제대로 되어 있는지 테스트
  • Squeeze Test : 하나의 인스턴스에 요청의 비율을 높여 부하를 주는 테스트, 어느 정도 요청부터 서비스 부하를 느끼는지 확인

4. api-gateway / webflux

  • spring cloud gateway선택

5. monitoring

  • 오픈소스 이용
  • 로그 : 컨테이너 ID, 서비스 ID, 배포 ID, Request ID, Pinpoint ID
  • apm : Pinpoint
  • metric : thanos + ceph + grafana
  • 알림 : sentry + toss ES alert + grafana

6. kafka

7. redis

참가 목걸이