← 모든 글

테스트 수가 늘어도 신뢰가 줄어드는 이유

flaky test와 false positive가 팀의 테스트 신뢰를 어떻게 갉아먹는지 실경험 회고

숫자는 늘었는데 믿음은 없었다

CI 대시보드에 테스트 케이스가 1,400개를 넘던 시점이 있었다. 커버리지 리포트는 78%. 숫자만 보면 꽤 탄탄해 보인다. 그런데 팀원들은 빨간 불이 켜져도 그냥 재시도 버튼부터 눌렀다.

“한 번 더 돌리면 통과해요”가 구두 인수인계 항목이 돼버린 것. 그게 문제의 진짜 시작이었다.

flaky 는 버그가 아니라 소음이다

flaky test 를 처음 마주한 건 외부 API 연동 테스트였다. 네트워크 레이턴시를 흉내 낸다며 time.sleep(1) 하나 박아뒀는데, CI 서버가 바쁜 시간대엔 그 1초가 충분하지 않았다. 주 2~3회 간헐적으로 터졌다.

  • 처음엔 flake rate 를 집계하지 않았다. 그냥 “가끔 터지는 테스트” 취급이었는데, 4주 후 통계를 뽑아보니 전체 빌드의 34%가 이 테스트 하나 때문에 실패 판정을 받고 있었다. 빌드 한 번에 15분이니까, 재시도 비용만 따지면 한 달에 엔지니어 1.5일치가 날아간 셈이다.
  • “재시도하면 되지 않나”라고 생각했던 적이 나도 있었다. 막상 재시도 로직을 CI에 심어두고 나니 더 나빴다. 실제로 서비스가 죽었을 때도 “어차피 한 번 더 돌리면 되겠지” 반응이 나왔다. 소음에 적응한 팀은 신호도 소음으로 처리한다.
  • 결국 해당 테스트를 quarantine 레이블로 분리하고, 별도 슬랙 채널에 주 1회 리포트 형태로 돌렸다. 메인 파이프라인 블로킹에서 제외하자마자 팀의 재시도 습관이 3주 안에 사라졌다. 숫자를 줄인 게 아니라 채널을 나눈 것만으로.

false positive 가 더 나쁜 이유

flaky 는 그나마 눈에 보인다. false positive 는 조용히 신뢰를 깎는다.

우리 코드베이스에 stub 을 과하게 쓰던 구간이 있었다. 서드파티 결제 모듈 연동부였는데, 실제 SDK 응답 구조가 바뀐 걸 모르고 6주를 지냈다. 테스트는 계속 초록불이었다. stub 이 예전 응답 형태를 반환하고 있었으니까.

  • 프로덕션에서 결제 오류가 터진 건 배포 직후가 아니라 12일 뒤였다. SDK 업데이트가 점진적으로 적용되는 방식이라서 늦게 터진 것인데, 그 12일 동안 CI 는 한 번도 빨간 불을 켜지 않았다. 테스트가 없는 것보다 false positive 가 더 위험한 이유가 여기 있다. 없으면 모른다는 걸 알지만, 있으면 안전하다고 착각한다.
  • 이후 그 구간에 contract test 를 도입했다. 외부 SDK 의 실제 응답 스키마를 JSON 파일로 고정해두고, 주기적으로 API sandbox 를 찔러 스키마 드리프트를 감지하도록 했다. 완벽하진 않지만 “stub 이 거짓말하고 있다”는 신호는 잡히게 됐다.

테스트 이름이 거짓말하는 경우

생각보다 많다. test_user_can_checkout_successfully 인데 실제로 검증하는 건 HTTP 200 반환 여부뿐인 경우. 응답 바디는 보지 않는다.

이런 테스트는 조용히 초록불을 켜면서 진짜 동작을 보장한다는 착각을 준다. 이름이 기대를 높이고, 구현이 기대를 채우지 못하는 구조. 리뷰 때 잡기도 어렵다. 테스트 코드는 “동작하는 코드”니까 꼼꼼히 안 보는 관성이 있다.

  • 한번은 PR 리뷰에서 테스트 커버리지가 85%라는 이유로 머지 승인을 빨리 받은 적이 있었다. 나중에 해당 경로를 직접 추적해보니 분기 커버리지(branch coverage)는 40% 수준이었다. 라인은 지나가지만 조건 분기를 전혀 건드리지 않는 테스트들이 숫자를 채우고 있었다.
  • 이후로 PR 체크리스트에 “이 테스트가 실패해야 하는 상황을 하나 댈 수 있는가”를 넣었다. 형식적이지만 효과는 있었다. 작성자가 직접 반례를 떠올리는 것만으로도 어설픈 assertion 이 한 줄씩 추가됐다.

신뢰 회복에 걸린 시간

quarantine 분리, contract test 추가, 체크리스트 항목 세 가지를 순서대로 적용했다. 팀에서 “재시도 먼저” 반응이 없어지는 데 두 달쯤 걸렸다.

빠르지 않다. 습관은 숫자보다 늦게 바뀐다. 테스트 수는 이틀 만에 바꿀 수 있지만, 빨간 불을 진지하게 보는 태도는 반복 경험이 쌓여야 생긴다. 결국 flaky 가 진짜 오류였던 사건이 두 번 지나고 나서야 팀 전체 반응이 달라졌다. 경험이 관성을 이긴다.

다음 한 가지

다음 분기에는 quarantine 버킷에 쌓인 테스트를 매월 첫째 주에 의무적으로 들여다보는 시간을 30분이라도 캘린더에 고정한다 — 격리가 영구 유배가 되지 않게.


🛒 이 글과 어울리는 추천 상품

위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.