QA 팀이 잘못된 것을 테스트하고 있는 이유, 그리고 그 원인인 데이터
요약
QA 테스트가 통과했음에도 버그가 발생하는 근본 원인은 도구나 프로세스가 아닌 '데이터의 실패'에 있습니다. 실제 운영 환경의 복잡한 엣지 케이스를 반영하지 못하는 수동 테스트 데이터의 한계와 데이터 드리프트 문제를 지적합니다.
핵심 포인트
- 테스트 데이터는 프로덕션의 실제 조건을 시뮬레이션해야 함
- 수동으로 작성된 픽스처는 인간의 상상력 한계로 커버리지가 낮음
- 스키마 진화에 따라 테스트 데이터와 운영 환경 간의 드리프트 발생
- 잘못된 데이터는 테스트 통과율만 높이는 '거짓된 확신'을 제공함
버그를 프로덕션(Production) 환경에 배포한 엔지니어링 팀들이 진행하는 거의 모든 사후 분석(Post-mortem) 과정에서는 항상 비슷한 대화가 오갑니다.
누군가는 "하지만 테스트는 통과했는데요"라고 말합니다. 그리고 실제로 통과했습니다. 단 하나도 빠짐없이 말이죠. QA 스위트(QA suite)는 깨끗하게 실행되었고, 스테이징 환경(Staging environment)도 괜찮아 보였지만, 버그는 결국 통과해 버렸습니다. 이는 테스트가 틀렸기 때문이 아니라, 테스트가 실행된 데이터가 버그를 잡아낼 만큼 정직하지 못했기 때문입니다.
이것은 아무도 말하고 싶어 하지 않는 QA 문제인데, 왜냐하면 이것은 프로세스의 실패(Process failure)나 도구의 실패(Tooling failure)가 아니기 때문입니다. 이것은 데이터의 실패(Data failure)입니다. 그리고 이는 대부분의 팀이 테스트 인프라에서 가장 흥미롭지 않다고 생각하는 부분 안에 숨어 있습니다.
테스트 데이터가 실제로 수행해야 하는 역할
대부분의 엔지니어에게 테스트 데이터가 무엇을 위한 것인지 물으면, 그들은 "테스트를 실행하기 위해서"와 같이 대답할 것입니다. 기술적으로는 맞지만, 정의로서는 거의 아무런 쓸모가 없는 답변입니다.
테스트 데이터는 애플리케이션이 프로덕션 환경에서 마주하게 될 실제 조건의 전체 범위를 시뮬레이션(Simulate)해야 합니다. 깨끗하고, 예상 가능하며, 해피 패스(Happy-path)인 조건들만이 아닙니다. 그 모든 것이어야 합니다. 모든 양식 필드를 올바르게 채우지만 예상치 못한 순서로 입력하는 사용자, 10년에 걸친 거래 내역이 있고 세 가지 다른 통화 유형을 가진 계정, 구독 등급이 세 번이나 마이그레이션(Migrated)되었고 결제 상태가 기술적으로는 유효하지만 할인 로직이 한 번도 본 적 없을 정도로 특이한 고객 등이 포함되어야 합니다.
테스트 데이터에 이러한 시나리오가 포함되지 않으면, 여러분의 테스트는 거짓된 확신을 만들어내는 확신 기계가 됩니다. 테스트는 안정적으로 통과합니다. 하지만 새로운 것은 아무것도 잡아내지 못합니다. 그리고 실제 엣지 케이스(Edge cases)에서 실제 사용자에게 영향을 미치는 중요한 버그들은 그대로 통과해 버립니다.
규모가 커질 때 발생하는 수동 데이터 작성 문제
대부분의 QA 팀은 항상 해왔던 방식대로 테스트 데이터를 구축합니다. 즉, 새로운 기능이 출시될 때마다 새로운 픽스처(Fixtures)를 점진적으로 수동으로 추가하는 방식입니다. 애플리케이션이 단순하고 팀 규모가 작은 초기 단계에서는 이 방식이 충분히 잘 작동합니다.
문제는 시간이 지남에 따라 두 가지 방향으로 동시에 심화됩니다.
첫 번째는 커버리지 (Coverage)입니다. 수동으로 작성된 픽스처 (Fixtures)는 그것을 작성한 사람이 생각한 시나리오만을 반영합니다. 시니어 엔지니어는 주니어 엔지니어보다 더 완전한 픽스처를 작성합니다. 스프린트(Sprint) 막바지에 지친 엔지니어는 휴식을 취한 상태의 엔지니어보다 덜 철저한 픽스처를 작성합니다. 누구도 의도적으로 불완전한 테스트 데이터를 작성하지는 않습니다. 단지 인간의 상상력에는 한계가 있으며, 엣지 케이스 (Edge cases)란 정의상 아무도 명확하게 기록할 만큼 상상하지 못한 시나리오일 뿐입니다.
두 번째는 드리프트 (Drift)입니다. 스키마 (Schema)가 진화함에 따라, 작성 당시에는 정확했던 픽스처들이 실제 운영 환경 (Production)의 현실과 점점 더 동떨어지게 됩니다. 컬럼 (Column)이 추가됩니다. 관계 (Relationship)가 변경됩니다. 새로운 비즈니스 규칙이 생기면 12개월 전에는 유효했던 값들의 조합이 이제 운영 환경에서는 불가능해질 수 있습니다. 하지만 픽스처에는 여전히 그 값이 남아 있고, 테스트는 여전히 그 값을 대상으로 실행되며, 테스트는 더 이상 존재하지 않는 세상의 상태를 검증하고 있기 때문에 통과율 (Pass rate)은 100%로 유지됩니다.
커버리지의 환상 (The Coverage Illusion)
이 부분이 진정으로 위험한 지점입니다. 높은 테스트 커버리지 지표는 형편없는 테스트 데이터 품질과 완전히 공존할 수 있습니다.
코드 커버리지가 95%에 달하더라도, 모든 테스트가 실제 운영 시나리오의 상위 10%만을 나타내는 데이터를 대상으로 실행될 수 있습니다. 커버리지 수치는 테스트 실행 중에 코드의 얼마나 많은 부분이 실행되었는지를 알려줄 뿐입니다. 그 코드를 실행한 데이터가 중요한 버그를 드러낼 만큼 충분히 현실적이었는지에 대해서는 아무것도 알려주지 않습니다.
모두가 모범적인 사용자처럼 보이는 수동 작성 픽스처를 대상으로 2,000개의 테스트를 실행하는 QA 팀은, 탈퇴한 계정, 결제 실패, 불완전한 프로필, 그리고 실제 운영 환경에서 나타나는 엣지 케이스 조합이 포함된 생성된 데이터 (Generated data)를 대상으로 500개의 테스트를 실행하는 팀보다 더 잘 보호받고 있는 것이 아닙니다. 두 번째 팀이 더 중요한 문제들을 더 많이 잡아냅니다. 첫 번째 팀은 더 인상적인 대시보드 (Dashboard)를 가질 뿐입니다.
생성된 테스트 데이터가 바꾸는 것
수기로 작성한 피스처 (Fixtures)에서 제어된 분포 (Distributions)를 가진 생성된 테스트 데이터로 전환할 때, 가장 먼저 변하는 것은 커버리지의 폭입니다. 이는 코드 커버리지 (Code Coverage)의 의미가 아니라, 시나리오 커버리지 (Scenario Coverage)의 의미입니다.
시나리오를 상상하며 테스트 데이터를 작성하는 것을 멈추고, 모집단 (Populations)을 명시하기 시작합니다. "이러한 속성을 가진 사용자를 생성하라" 대신, "15%는 프로필이 불완전하고, 8%는 결제 실패 상태이며, 5%는 계정 생성 후 5년이 지났고, 3%는 이탈 후 최소 한 번 이상 재활성화된 사용자 10,000명을 생성하라"라고 기술합니다. 생성기 (Generator)가 변동성을 처리합니다. 여러분의 테스트는 누군가가 수요일 오후에 떠올린 예시 세트가 아니라, 운영 환경 (Production)을 반영하는 모집단을 대상으로 실행됩니다.
두 번째로 변하는 것은 일관성 (Consistency)입니다. 생성된 데이터는 유지 관리하는 것이 아니라 재생성하는 것이기 때문에 데이터 드리프트 (Drift)가 발생하지 않습니다. 스키마 (Schema)가 변경되면 생성 파라미터 (Generation Parameters)를 업데이트하고 다시 생성하면 됩니다. 피스처 (Fixtures)는 누군가 업데이트를 기억할 필요 없이 최신 상태를 유지합니다.
세 번째 — 그리고 QA 리드 (QA Leads)들이 가장 관심을 가질 만한 부분은 — 엣지 케이스 (Edge Case) 발견이 우연이 아닌 의도적인 과정이 된다는 점입니다. 누군가가 해당 케이스를 위한 피스처를 작성하기를 바라는 대신, 테스트하고자 하는 특이 상태 (Unusual States)의 분포를 정확하게 지정할 수 있습니다.
SyntheholDB가 QA 워크플로우에 어떻게 적용되는가?
이것은 생성된 테스트 데이터를 처음 시작하는 대부분의 QA 팀에게 가장 실질적인 의미를 갖는 워크플로우 패턴입니다.
당신은 테이블, 관계, 그리고 값의 분포를 제어해야 하는 비즈니스 로직(business logic)을 일반적인 영어로 기술합니다. SyntheholDB는 모든 연결된 테이블에 걸쳐 외래 키(foreign keys)가 올바르게 해결되고, 당신이 지정한 통계적 특성(statistical properties)이 출력물에 반영되는 관계형으로 일관된(relationally consistent) 데이터셋을 생성합니다. 내보내기(export) 전에 PII(개인정보) 스캔이 자동으로 실행되므로, 실제 고객 기록과 유사한 데이터가 테스트 환경에 포함되지 않습니다. 생성된 CSV 시드(seeds)는 QA 데이터베이스, CI 파이프라인 또는 로컬 환경으로 직접 삽입됩니다.
QA 팀의 워크플로우 변화는 최소한입니다. 동일한 테스트가 동일한 데이터베이스를 대상으로 실행됩니다. 차이점은 이제 데이터베이스가 애플리케이션을 확인(confirming)하는 대신, 실제로 애플리케이션에 도전(challenging)하는 데이터를 포함하고 있다는 점입니다. 무료 티어는 db.synthehol.ai에서 바로 이용 가능합니다 — 신용카드도, 설정 오버헤드(configuration overhead)도 필요 없습니다.
중요한 관점의 전환 (The Reframe That Matters)
훌륭한 QA는 테스트의 개수에 달려 있지 않습니다. 그것은 테스트가 실행되는 조건의 정직함에 달려 있습니다.
실제 운영 환경의 사용자들이 매일 생성하는 엣지 케이스(edge cases), 실패 상태(failure states), 그리고 특이한 조합들을 포함하여, 현실적인 분포를 가진 생성 데이터로 실행되는 테스트 스위트(test suite)는 모두가 이상적인 사용자처럼 보이는 정교하게 수기로 작성된 픽스처(fixtures)로 실행되는 스위트보다 더 적은 테스트로도 더 의미 있는 버그를 잡아낼 것입니다.
데이터가 곧 테스트입니다. 대부분의 팀은 아직 데이터를 그런 방식으로 다루지 않았을 뿐입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기