본문으로 건너뛰기

12.3 Anti-pattern Catalog

1. Hard wait​

await page.waitForTimeout(3000);

빠른 환경에서는 3초를 낭비하고 느린 환경에서는 여전히 실패합니다. 필요한 제품 상태를 assertion합니다.

2. 긴 CSS/XPath​

page.locator('div:nth-child(4) > div.card > button.primary');

DOM layout과 styling에 coupling됩니다. Role, label, test id 같은 계약을 사용합니다.

3. .first()로 strictness 숨기기​

여러 match 중 첫 번째가 우연히 맞는 상태입니다. Scope와 accessible name을 명확히 합니다.

4. force: true 기본 사용​

Overlay, animation, disabled state 같은 실제 사용자 문제를 건너뜁니다. Root cause를 고치고 의도적 특수 case에만 씁니다.

5. Retry면 해결됐다고 판단​

Retry pass는 flaky 분류입니다. 최초 failure trace와 발생률을 추적합니다.

6. Test 사이 state 공유​

let createdOrderId: string;

Parallelism과 failure recovery를 깨뜨립니다. 각 test가 setup하거나 explicit serial workflow로 제한합니다.

7. beforeAll에 거대한 UI setup​

한 번 실패하면 group 전체가 무너지고 worker restart에서 다시 실행될 수 있습니다. API seed, fixture, project dependency를 검토합니다.

8. Page Object가 assertion을 모두 숨김​

어떤 결과를 기대하는지 test body에서 사라집니다. Reusable invariant는 object에 둘 수 있지만 scenario-specific expected result는 test가 표현합니다.

9. 모든 API를 mock​

Frontend와 backend contract drift를 놓칩니다. Real integration test를 소수 유지합니다.

10. 모든 것을 E2E로 검증​

느리고 원인 localization이 어렵습니다. Unit/component/API layer로 분배합니다.

11. Snapshot 무조건 update​

제품 회귀를 baseline으로 승인해 버립니다. Diff와 requirement를 먼저 리뷰합니다.

12. Trace, HAR, storage state commit​

Token과 개인정보가 포함될 수 있으므로 ignore, sanitize, retention, access control을 적용합니다.

13. networkidle을 readiness로 사용​

Polling, streaming, analytics 때문에 영원히 idle하지 않거나 너무 일찍 idle할 수 있습니다. 제품 marker를 기다립니다.

14. Browser마다 같은 failure를 세 번 보여주기​

Browser-independent logic은 Chromium smoke에 두고 compatibility 위험이 있는 scenario만 full matrix로 실행합니다.

15. Test title이 implementation detail​

“button click test” 대신 “사용자가 주문을 취소한다”처럼 business outcome을 표현합니다.

Review 질문​

  • 이 workaround가 제품 bug를 숨기는가?
  • Failure message만으로 의도를 알 수 있는가?
  • Test가 더 빠른 layer로 내려갈 수 있는가?
  • Artifact가 root cause를 설명하는가?
  • 이 test를 누가 소유하고 언제 삭제하는가?

참고: Best Practices