테스트의 목적은 코드를 실행하거나 Coverage를 높이는 것이 아니라, 시스템이 지켜야 할 속성을 위반하는 반례를 찾는 것입니다. 테스트 결과가 반복 가능하고 실패 원인이 분명해야 배포 판단에 사용할 수 있습니다.
검증할 속성을 먼저 정한다
- 각 테스트는 입력 사례보다 먼저 지켜야 할 invariant와 관찰 방법을 정합니다. Assert 없이 실행만 하는 테스트는 검증이 아닙니다.
- 내부 상태와 사용자에게 보이는 최종 outcome을 모두 봅니다. 내부 상태가 정상이어도 데이터 누락이나 잘못된 Side Effect가 남을 수 있습니다.
- Mock은 내가 가정한 동작만 증명합니다. 외부 서비스와의 실제 경계는 Contract Test로 별도 검증합니다.
- Coverage는 실행하지 않은 코드를 찾는 지표일 뿐 테스트의 정확성을 증명하지 않습니다. 중요한 변경에서는 작은 결함을 의도적으로 넣어 테스트가 실패하는지 확인하는 Mutation Testing을 선택적으로 사용합니다.
희귀한 실패를 자주 발생시킨다
- 입력뿐 아니라 Operation 순서, 설정, 동시성, 실행 시간도 무작위화합니다. 실패하면 seed와 실행 조건을 보존합니다.
- 모든 기능을 매번 켜면 서로 상태를 상쇄하거나 제한된 실행 안에서 각 경로가 얕게 탐색될 수 있습니다. Swarm Testing은 실행마다 일부 Feature나 Operation을 제외하여 다른 상태 공간을 깊게 탐색합니다.
- Buggification은 테스트에서 실제 계약상 가능한 오류를 의도적으로 주입하여 Retry·Fallback·복구 경로를 반복 검증합니다. Production에 존재할 수 없는 실패를 만들어서는 안 됩니다.
- 긴 Timeout, 대용량 임계값, 드문 Background Job은 테스트 환경에서 축소합니다. 의미를 바꾸지 않으면서 Failover·Shard 분할·만료 같은 경로가 실행 시간 안에 발생하도록 합니다.
검증 시점을 나눈다
- 마지막에만 검사하면 중간에 깨졌다가 우연히 복구된 상태를 놓칩니다. 작업과 invariant 검증을 번갈아 실행합니다.
- 데이터 손상처럼 한순간도 허용할 수 없는 Safety는 계속 검사합니다.
- 장애 후 복구처럼 시간이 필요한 Liveness는 정해진 기한 안에 결국 성립하는지 검사합니다.
- 종료 후에만 의미가 있는 일관성·정리 상태는 작업이 멈춘 뒤 별도로 검사합니다.
실패를 재현 가능한 자산으로 만든다
- Random seed, 설정, Feature 조합, Fault와 Operation 순서를 함께 남깁니다. 재실행할 수 없는 실패는 수정 여부도 검증할 수 없습니다.
- 실패 시퀀스는 원인을 유지하는 최소 사례로 줄입니다. Property-based Testing의 shrinking이나 단계 제거로 불필요한 이력을 없앱니다.
- 수정한 실패는 고정된 Regression Test로 남깁니다. 무작위 탐색이 같은 반례를 다시 찾기를 기다리지 않습니다.
테스트 신호를 보호한다
- 같은 코드가 통과와 실패를 반복하는 Flaky Test는 테스트 결함 또는 실제 비결정성의 증거입니다. 단순 재시도로 숨기지 않습니다.
- 시간, 난수, 파일, 전역 상태와 외부 네트워크를 통제하여 테스트를 격리합니다. 격리 때문에 실제 경계를 대체했다면 별도 Contract Test로 그 가정이 맞는지 확인합니다.
- 검증하려는 속성을 가장 싸고 좁게 깨뜨릴 수 있는 테스트를 선택합니다. 전체 시스템의 협력 결과가 대상일 때만 E2E 범위를 사용합니다.
References
- Techniques for better software testing — Randomness, Buggification, 지속 검증과 테스트 설정
- Swarm Testing — Feature omission diversity의 원 논문과 세 사례 실험
- Long Term Effects of Mutation Testing — Mutation과 실제 결함의 연관성
- Flaky Tests at Google and How We Mitigate Them — Flaky Test가 검증 신호에 미치는 영향
- Hermetic Servers — 외부 의존성을 통제한 E2E 환경
- Contract Test — Test Double과 실제 경계의 일치 검증
- Anatomy of a test — 반례 저장·재실행과 shrinking