- analysis/·source-index·state.json 을 final/document.md 제2부·제3부로 접었다. SSOT 는 하나다 - 파일럿 — commit-ambiguity-as-a-result 를 새 기준으로 재선별. 후보 14 → 글감 5 (PROMOTE 5 · MERGE_INTO 3 · KEEP_IN_SSOT 4 · 보류 2). 기록 5건을 다시 썼고 그림 1개를 techviz 로 만들었다 - 재선별이 잡은 것: 제1부 §6.2·§11.1 이 자기 §13.2 와 어긋나 있었다(레인을 안 돌렸다 vs 돌렸다) — 정정. 이미 답이 나와 있던 Question 을 HEAD 재실행 질문으로 다시 세웠다. Concept 이 인용한 코드가 SSOT 에 없어 뺐다 - candidateScope·sourceRepository 기록. 나머지 43개 주제는 재선별 대기(PENDING 905) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
94 lines
6.0 KiB
Markdown
94 lines
6.0 KiB
Markdown
---
|
|
kind: CASE
|
|
slug: test-names-that-assert-what-their-bodies-do-not
|
|
title: 이름이 검사한다고 말하는 것을 본문이 검사하지 않는 테스트 넷
|
|
topic: what-a-gate-does-not-prove
|
|
project: clean-architecture-backend-template
|
|
status: 게시 전
|
|
sourceRevision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
|
rootTreeNode: case:test-names-that-assert-what-their-bodies-do-not
|
|
evidenceCapturedOn: 2026-09-01
|
|
assets:
|
|
- key: test-names-that-assert-what-their-bodies-do-not
|
|
file: ../../../final/evidence/rendered/test-names-that-assert-what-their-bodies-do-not.svg
|
|
evidence:
|
|
- ../../../final/evidence/raw/test-names-that-assert-what-their-bodies-do-not.txt
|
|
source:
|
|
- 원본 분석 절은 final/document.md#a19-messaging-pulsar-experimental §17.3 · final/document.md#a19-messaging-nats-experimental §17.4 · final/document.md#a20-grpc-advanced-bootstrap §17.4 이다.
|
|
---
|
|
|
|
# 이름이 검사한다고 말하는 것을 본문이 검사하지 않는 테스트 넷
|
|
|
|
네 테스트가 이름과 설명 메시지로 무엇을 붙든다고 말하는데 본문이 다른 것을 확인하거나 아무것도 배제하지 않는다. 어느 것도 잘못된 동작을 통과시키지는 않는다. 틀리는 것은 커버리지 지도다.
|
|
|
|
## 관계
|
|
|
|
- **빠뜨림이 통과가 되는 게이트는 게이트가 아니다**
|
|
같은 계열의 규칙이다.
|
|
- **다중 타깃 검증을 확인한다는 테스트가 다른 가드에 걸려 통과했다**
|
|
같은 형태가 다른 리프에서 나타난 사례다.
|
|
- **산문이 선언한 게이트는 빌드에 있는 게이트가 아니다**
|
|
이 사례가 그 규칙이 왜 오래 눈에 띄지 않는지를 설명한다.
|
|
|
|
## 문제
|
|
|
|
테스트 이름은 이 저장소에서 문장으로 쓰인다. 무엇을 붙드는지를 이름이 말하고, 설명 메시지가 왜 그것을 붙드는지를 말한다. 그 관행이 읽기를 빠르게 만든다.
|
|
|
|
빠른 읽기는 이름을 커버리지 지도로 쓰게 만든다. 어떤 규칙에 테스트가 있는지 확인할 때 본문 대신 이름을 센다.
|
|
|
|
## 결론
|
|
|
|
네 곳에서 이름과 본문이 갈린다.
|
|
|
|
첫째. 이름이 검증기가 키 공유 프로파일을 받아들인다고 말하는데 본문에 검증기가 없다. 프로파일 생성자만 부르고 예외가 나지 않는 것을 확인한다. 그 리프에서 검증기를 언급하는 유일한 테스트 이름이 이것이라, 이름만 읽으면 검증기에 커버리지가 있다고 읽힌다. 실제로 그 검증기는 저장소 전체에서 자기 선언 한 줄 말고 아무 데도 없다.
|
|
|
|
둘째. 이름이 소비자 팩토리 없이 만든 전송이 등록을 거절한다고 말한다. 그 거절은 기본 팩토리가 던지는 예외다. 본문은 등록 메서드에 널을 넘겨 첫 줄의 널 검사에 걸린다. 단언하는 예외 타입도 그 널 검사의 것이다. 겨냥한 거절 코드는 저장소에서 한 번도 실행되지 않는다.
|
|
|
|
셋째. 설명 메시지가 모든 결과가 영으로 보고되던 회귀를 막는다고 적는다. 단언은 경과 시간이 영 이상이라는 것이다. 경과 시간은 시작 시점에서 잰 값이라 음수가 될 수 없으므로 이 단언은 구현이 무엇을 하든 통과한다. 영을 배제하려던 단언이 영을 통과시킨다.
|
|
|
|
넷째. 이름이 상위 등급이 되는 데 더 긴 담금이 필요하다고 말한다. 본문이 실제로 평가하는 전이는 철회 방향이다. 겨냥한 등급이 열거형에 없어서 그것을 밟을 방법이 없었고, 남은 값 중 하나를 골라야 했던 흔적이다.
|
|
|
|
넷 다 통과한다. 그리고 넷 다 그 아래에 진짜 공백을 하나씩 두고 있다. 첫째와 둘째는 호출자 없는 검증기와 실행되지 않는 거절 경로, 셋째는 측정되지 않는 경과 시간, 넷째는 존재하지 않는 등급을 위해 쓰인 임계값이다. 이름이 커버리지를 주장했기 때문에 그 공백들이 오래 보이지 않았다.
|
|
|
|
## 검증 환경
|
|
|
|
OpenJDK : 21.0.12
|
|
Gradle : 9.0.0
|
|
확인 방식 : 테스트 본문과 이름 및 설명 메시지 대조, 그리고 단언 의미론 확인
|
|
소스 수정 : x
|
|
|
|
## 재현 조건
|
|
|
|
1. 각 테스트의 이름과 설명 메시지가 무엇을 주장하는지 적는다.
|
|
2. 본문이 실제로 만드는 객체와 부르는 메서드를 나열한다.
|
|
3. 단언이 배제하는 값의 집합을 구한다.
|
|
4. 이름이 지목한 코드 경로에 도달하는지 확인한다.
|
|
|
|
## 본문
|
|
|
|
<!-- body:start -->
|
|
|
|
네 형태가 같은 결과를 낳는다.
|
|
|
|
## PulsarProfile 참조 위치
|
|
|
|
:::evidence key="test-names-that-assert-what-their-bodies-do-not" alt="코드베이스에서 PulsarProfile 를 검색한 출력 5줄. 이 기록이 세는 참조가 그 출력에 그대로 보인다." caption="PulsarProfile 코드베이스 검색 — 5줄 · exit 0" zoom="true"
|
|
:::
|
|
|
|
## 넷이 각각 놓치는 것
|
|
|
|
1. 이름이 `theValidatorAccepts…` 인데 본문에 검증기가 없다 — `PulsarProfile` 생성자만 부른다. 그 리프에서 검증기를 언급하는 유일한 테스트 이름이라, 이름만 읽으면 커버리지가 있다고 읽힌다.
|
|
2. 이름이 "소비자 팩토리 없이 만든 전송이 등록을 거절한다" 인데 본문은 `register(null)` 을 불러 첫 줄의 널 검사에 걸린다 — 겨냥한 `PULSAR_CONSUMER_NOT_CONFIGURED` 는 한 번도 실행되지 않는다.
|
|
3. `as()` 가 "모든 결과가 `Duration.ZERO` 였다" 는 회귀를 막는다고 적는데 단언이 `isGreaterThanOrEqualTo(Duration.ZERO)` 라 `Duration.ZERO` 도 통과한다 — 구현이 무엇을 하든 참이다.
|
|
4. 이름이 "Stable default 가 되는 데 더 긴 담금이 필요하다" 인데 실제로 평가하는 전이는 `ADVANCED_STABLE → DISABLED`(철회)다.
|
|
|
|
## 틀리는 것은 커버리지 지도다
|
|
|
|
어느 것도 잘못된 동작을 통과시키지는 않는다. 그래서 그 아래의 진짜 공백이 오래 눈에 띄지 않았다.
|
|
|
|
## 확인하지 못한 것
|
|
|
|
테스트를 실행하지 않았다. 판정은 단언 의미론과 호출 경로에 대한 것이다.
|
|
|
|
<!-- body:end -->
|