Skip to content

Fix: 현장 측정에서 찾은 조용한 실패 둘을 고친다 - #120

Merged
jjh75607 merged 5 commits into
masterfrom
fix/silent-failures-from-field-test
Aug 27, 2026
Merged

jjh75607 merged 5 commits into
masterfrom
fix/silent-failures-from-field-test

Conversation

@jjh75607

Copy link
Copy Markdown
Owner

배경

이 라이브러리를 공개 프로젝트 열일곱 곳의 테스트 스위트에 실제로 붙여 봤다. 라이브러리를 뺀
대조군과 붙인 계측군을 매번 함께 돌려 차이를 봤고, 수치를 낸 표본이 다섯, 결함을 드러낸 실패가
셋이다. 측정 기록은 저장소 밖 oss-contrib/query-counter-field-test/RESULTS-2026-08-27.md 에 있다.

거기서 나온 결함 둘을 고친다. 둘 다 조용히 잘못되는 종류라 이 저장소가 이미 두 번 겪은 것과
같은 성질이다.

고친 것

하나. 감싼 DataSource 가 던진 예외의 타입이 바뀌었다.

Method.invoke 는 대상이 던진 예외를 InvocationTargetException 으로 감싸는데 그것을 벗기지
않았다. 그러면 선언되지 않은 체크 예외라 프록시가 다시 UndeclaredThrowableException 으로
감싼다. DB 설정이 깨진 프로젝트로 대조한 결과다.

대조군 계측군(고치기 전)
예외 사슬 SQLException → GenericJDBCException SQLException → InvocationTargetException → UndeclaredThrowableException
하이버네이트 변환기 돈다 안 돈다
메시지 실제 원인 InvocationTargetException: null

테스트에서만 도는 라이브러리가 테스트가 받는 예외의 종류를 바꾼 것이다. 제약 위반을 검증하는
테스트라면 기대하던 DataIntegrityViolationException 대신 엉뚱한 예외를 받는다. "붙였다는 이유로
남의 테스트가 깨지면 안 된다" 는 첫 성질을 정면으로 어긴다.

둘. 쿼리가 0건인 테스트가 보고에서 통째로 빠졌다.

설정이 쿼리 기록 경로를 타고 테스트 경계로 오는 구조라, 쿼리가 없으면 설정도 안 와서 보고가 한
줄도 안 나왔다. 그래서 쿼리가 0건인 것과 계측이 안 붙은 것을 구별할 수 없었다. 계측이 안
붙는 문제를 #111, #112 로 고쳤는데 그것이 되살아나도 알아차릴 방법이 보고 모드에 없던 셈이다.
어느 스위트는 237개 중 88개가 침묵했다.

리스너가 hasApplicationContext() 로 이미 떠 있는 것을 확인한 뒤에만 설정을 되살린다.
컨텍스트 로딩을 강제하지 않는다는 제약은 그대로다. 그 조건을 지키는지 검증하는 테스트를 함께
넣었다.

검증

표본 여덟을 고치기 전후로 돌려 대조했다. 검증 자체가 변수가 되지 않도록, 고치기 전에 로컬
스냅샷으로 한 번 돌려 기준선과 같은 것을 먼저 확인했다.

표본 보고 0건 보고 N+1 경고 예외 뒤틀림
petclinic-rest 149 → 232 0 → 83 36 → 36 0
표본 B 229 → 333 0 → 104 23 → 23 0
표본 C 15 → 52 0 → 37 0 → 0 0
표본 D 19 → 39 0 → 20 2 → 2 0
표본 E 25 → 33 0 → 8 9 → 9 0
표본 F 0 0 0 3 → 0
표본 G 0 0 0 1 → 0

침묵하던 테스트 252건이 보고에 들어왔고 N+1 판정은 한 자리도 안 바뀌었다.
라이브러리 테스트 206건과 ./gradlew build(Spotless 포함) 통과.

표본 이름을 가린 것은 사람이 특정되는 팀 프로젝트이기 때문이다. 거기서 나온 것은 이 라이브러리를
고치기 위한 표본이지 그 코드에 대한 지적이 아니다.

함께 넣은 문서

N+1 검사가 함께 잡는 세 가지를 README 두 벌에 적었다. 판정 기준이 "같은 SELECT 모양에 다른
파라미터 값" 이라 N+1 이 아닌데 그 모양이 되는 테스트 방식이 있다. 한 테스트에서 찾는 경우와 못
찾는 경우를 함께 확인할 때, 페이징을 다음 장으로 넘기며 확인할 때, 생성과 수정과 삭제를 차례로
할 때다. 표본 넷에서 보고된 83개 중 38개가 그랬고, 몇 개나 보이는지는 검사 대상 코드보다
스위트를 어떻게 썼는가에 훨씬 크게 좌우됐다
(46개 중 4개인 스위트와 25개 전부인 스위트가 있었다).
반복 횟수로는 진짜와 가릴 수 없다는 것도 적었다.

판정 동작은 바꾸지 않았다. 억제 규칙을 세울 근거가 아직 부족하다. 표본 하나로 세운 규칙이
표본 둘에서 깨진 적이 있다.

CLAUDE.md 의 낡은 서술 둘(QueryCountVerifier 빚 수치, 리스너가 컨텍스트를 만질 수 없다는
서술)을 고치고, 릴리스 절차 70줄을 docs/RELEASING.md 로 분리했다.

@jjh75607
jjh75607 merged commit 8988acf into master Aug 27, 2026
6 checks passed
@jjh75607
jjh75607 deleted the fix/silent-failures-from-field-test branch August 27, 2026 04:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant