Bench에서 분자를 삭제하는 시나리오가 있다
Scenario: 분자를 삭제한다
Given Bench 페이지에 진입한다
When 첫 번째 분자를 삭제한다
Then 분자가 삭제되었음을 확인한다
검증이 매번 PASS였다
그런데 Then Step 코드를 열어보니 이랬다
@then("분자가 삭제되었음을 확인한다")
def verify_molecule_removed(bench_page, bench_context):
bench_page.take_screenshot("molecule_deleted")
logger.info("✓ 분자 삭제 완료")
스크린샷 찍고, 로그에 체크마크 출력하고, pytest는 PASS를 반환한다
실제로 분자가 삭제되었는지는 아무도 확인하지 않는다
삭제 API가 500을 반환해도 PASS다
화면에 분자가 그대로 남아 있어도 PASS다
이 패턴의 이름: Silent Pass
logger.info + take_screenshot 조합은 사람 눈에 "검증"처럼 보인다
콘솔에 ✓ 분자 삭제 완료가 출력되고, 스크린샷 파일도 저장된다
그래서 코드 리뷰에서도 잘 안 걸린다
하지만 코드 레벨에서 assert가 한 줄도 없다
예외가 발생하지 않는 한 무조건 통과한다
같은 패턴이 Given에도 있었다
@given("모든 단백질이 비활성화된 상태이다")
def all_proteins_deactivated(protein_page):
logger.info("✓ 단백질 비활성화 (프로젝트 초기 상태)")
"프로젝트 초기 상태"라는 가정 아래 상태 확인 없이 통과한다
전체 스위트를 순차 실행하면 이전 시나리오가 단백질을 활성화한 채로 남겨둘 수 있다
그래도 이 Given은 항상 통과하고, 이후 When에서 엉뚱한 상태를 기반으로 동작한다
해결: 변화량 기반 검증
삭제를 검증하려면 "삭제 전 상태"를 알아야 한다
@when("첫 번째 분자를 삭제한다")
def delete_first_molecule(bench_page, bench_context):
# 삭제 전 분자 수 기록
bench_context["molecule_count_before_delete"] = (
bench_page.get_displayed_molecule_count()
)
bench_page.delete_first_molecule()
When에서 액션을 실행하기 전에 현재 상태를 bench_context에 저장한다
@then("분자가 삭제되었음을 확인한다")
def verify_molecule_removed(bench_page, bench_context):
count_before = bench_context["molecule_count_before_delete"]
count_after = bench_page.get_displayed_molecule_count()
assert_with_screenshot(
bench_page,
count_after < count_before,
f"분자 수 감소해야 함 (이전: {count_before}, 현재: {count_after})"
)
Then에서 액션 후 상태를 조회하고, 변화량을 비교한다
삭제가 실패하면 count_after == count_before이고, assert가 실패하면서 스크린샷과 함께 정확한 메시지를 남긴다
Given 사전조건도 동일하게 적용
@given("모든 단백질이 비활성화된 상태이다")
def all_proteins_deactivated(protein_page):
is_deactivated = protein_page.is_bench_protein_deactivated()
given_precondition(
protein_page,
is_deactivated,
"단백질이 비활성화 상태가 아닙니다",
"all_proteins_deactivated"
)
given_precondition은 조건이 불충족하면 pytest.fail로 즉시 중단한다
"사전조건이 맞지 않으면 검증을 시작하지 않는다"는 원칙이다
Silent Pass 감지 체크리스트
| 항목 | 위험 신호 |
|---|---|
| Then Step에 `assert`가 없다 | `logger.info`만으로 PASS 처리 |
| Given Step에 상태 확인이 없다 | "초기 상태"라고 가정만 |
| `take_screenshot`만 호출한다 | 사람용 증거만 남기고 코드 검증 없음 |
| 예외 없이 항상 통과한다 | 어떤 상태에서든 PASS |
자동화 검증에서 가장 위험한 코드는 "실패하는 검증"이 아니라 "항상 통과하는 검증"이다
실패하는 코드는 즉시 알 수 있다
하지만 항상 통과하는 코드는 "검증이 동작하고 있다"는 거짓 신뢰를 준다
이번에 review_checklist.sh에 "Then Step에 assert 없이 logger.info만 사용" 패턴 탐지를 추가했다
# Then Step에서 assert 없이 logger.info만 있는 함수 탐지
grep -n "def.*then\|def.*verify\|def.*confirm" "$file" | while read line; do
# 해당 함수 범위 내에 assert가 없으면 경고
done
코드 작성 완료 시점에 자동으로 피드백된다
'TIL > Claude Code' 카테고리의 다른 글
| [TIL][Playwright] pages/ 전체 210개 wait_for_timeout을 0개로 제거한 4단계 과정 (0) | 2026.04.14 |
|---|---|
| [TIL][Python] except Exception이 코드 버그를 "요소를 못 찾았다"로 위장시킨다 (0) | 2026.04.12 |
| [TIL][Playwright] 모달이 버튼 인덱스를 밀어낸다 — nth() 로케이터의 함정 (0) | 2026.04.04 |
| [TIL][Claude Code] Playwright MCP 로 E2E 디버깅하기 — browser_snapshot 워크플로우 (2) | 2026.04.02 |
| [TIL][Claude Code] "이게 최선이야?" 를 자동으로 묻게 만들기 (0) | 2026.03.30 |