시나리오 문서 0건이던 77페이지 웹앱에 4레이어 테스트 구조를 세우고, 금액 계산은 E2E에서 떼어 단위 테스트로 격리했습니다. 공유 코어 패키지는 테스트 759개로 커버리지 42 → 69%.
AI로 테스트를 '많이' 만드는 건 쉽습니다. 어려운 건 그 테스트가 무엇을 정답으로 삼는지, 어느 레이어에서 무엇을 잡는지를 정하는 일입니다. 회사 웹앱과 개인 프로젝트에서 같은 구조를 썼습니다.
01사례
- TM03-1
4레이어 — 명세에서 실행까지 역추적되는 구조
- 문제
- 77개 페이지를 운영하면서 체계화된 시나리오 문서가 0건. 배포 전마다 손으로 눌러봤고, 어떤 테스트가 어떤 요구를 검증하는지 아무도 답할 수 없었습니다.
- 설계
- 행동 명세(WHAT) → 시나리오 카드(HOW) → 실행(Cypress E2E·Vitest 단위) → 수동 확인(QA 체크리스트 CSV)의 4레이어. 시나리오 카드에는 자동화가 못 잡는 것을 사람이 5초 안에 확인하는 3항목을 내장했습니다.
- 결과
- 페이지 커버 77/77, 시나리오 약 700건(문서 78개), Cypress 케이스 515건(실행 가능 300·skip 215), QA 체크리스트 83항목. 사내 AI 활용 공유 세션에서 발표했습니다.
- TM03-2
금액 계산은 E2E가 아니라 단위 테스트의 영역
- 문제
- 쿠폰·포인트·배송비 계산을 E2E로 검증하면 느리고, 실패해도 어느 계산이 틀렸는지 바로 안 보입니다.
- 설계
- 계산 로직을 화면에서 떼어 프레임워크 독립 코어 패키지로 옮기고, 그 패키지에 단위 테스트를 먼저 깔았습니다. 쿠폰 상호 배타(주문/상품/배송 쿠폰 간 상호 초기화), 상품쿠폰 per-unit 계산 등 금액 로직을 모바일 앱 구현과 1:1로 정합시켰습니다.
- 결과
- 코어 패키지 단위 테스트 759개(71개 파일), statement 커버리지 42.0% → 69.3%. 이후 1,022개. 화면 쪽 계산 로직 단위 테스트는 약 570ms에 돌아 매 저장마다 실행합니다.
- TM03-3
리팩토링의 회귀를 테스트로 봉인
- 문제
- 주문 도메인 9개 페이지를 4계층으로 옮기는 과정에서 송장번호 버튼 미노출, 클레임 카운트 누적 같은 회귀가 났습니다.
- 설계
- 회귀를 원인 커밋 단위로 역추적해 수정하고, 같은 회귀가 다시 나지 않도록 엔티티·useCase 단위 테스트로 봉인했습니다. 어드민 전체에는 도메인별 단위 테스트와 Cypress e2e(설정 intercept 기반)를 3주에 걸쳐 도입했습니다.
- 결과
- 주문 도메인 단위 테스트 82개, 어드민 전체 Vitest 1,345개(156개 파일). 전환 중 computed 내부 ref 부수효과로 금액 표시가 흔들릴 수 있던 잠복 결함 3건을 발굴했습니다.
- TM03-4
개인 프로젝트 — 인수 테스트를 검증 AI가 요구사항에서 뽑는다
- 문제
- 구현한 사람(또는 구현 AI)이 테스트를 쓰면 구현의 해석이 그대로 테스트가 됩니다.
- 설계
- 각(Gak)에서는 요구사항이 승인된 뒤 다른 벤더의 검증 AI가 요구사항 문서만 보고 인수 테스트 케이스를 작성합니다. 구현 AI는 그 케이스를 통과시키는 방향으로 구현합니다.
- 결과
- 화면 3개 인수 테스트 109건(BLOCKED 7건 별도 관리), 백엔드 자동 테스트 289개. Orbit은 pytest 65·Vitest 102·Playwright e2e 29를 CI에서 실행합니다.
02남은 규칙
- 01테스트는 명세에서 실행까지 역추적돼야 한다. 어떤 요구를 검증하는지 답할 수 없는 테스트는 없는 것과 같다.
- 02계산 로직은 화면에서 떼어 단위 테스트로 잡는다. E2E는 흐름을 본다.
- 03리팩토링 회귀는 고치고 끝내지 않고 테스트로 봉인한다.
- 04인수 테스트는 구현자가 아닌 쪽이 요구사항에서 뽑는다.