AI 생성 테스트가 프로덕션에 도달하는 버그를 계속 놓치는 이유
요약
AI를 이용한 테스트 생성 시 단순히 테스트의 양(Volume)을 늘리는 것이 실제 버그를 잡는 데 한계가 있음을 지적합니다. 버그는 개별 필드가 아닌 필드 간의 상호작용에서 발생하므로, 단순 프롬프팅을 넘어 판단력(Judgment)과 실행(Mechanical)을 분리하는 접근이 필요합니다.
핵심 포인트
- AI 생성 테스트는 주로 필드 단위의 변이에 집중하여 상호작용 버그를 놓침
- 단순히 테스트 개수를 늘리는 것은 판단력 없는 속도 최적화에 불과함
- 필드 간의 복잡한 논리적 결합을 검증하기 위해서는 고도화된 추론이 필요함
- 테스트 생성 과정을 '무엇을 테스트할지 결정하는 판단'과 '테스트 작성'으로 분리해야 함
볼륨(Volume)은 커버리지(Coverage)와 같은 것이 아닙니다. 다음은 대부분의 팀이 비용을 치르기 전까지는 알아차리지 못하는 실패 모드입니다.
AI 모델에게 API 엔드포인트에 대한 테스트를 생성하라고 요청하면, 모델은 몇 초 만에 기꺼이 30개의 테스트를 만들어낼 것입니다. 결과물을 훑어보면 누락된 필드, 잘못된 타입, 경계값(boundary values) 및 몇 가지 에러 케이스 등 매우 포괄적으로 보입니다. 이를 배포하고 몇 주가 지나면, 프로덕션 장애가 발생하는데, 그 원인을 추적해 보면 그 30개의 테스트 중 그 어떤 것도 잡아내지 못했을 버그로 밝혀집니다.
이것은 드문 실패 사례가 아닙니다. 테스트 생성(test generation)이 판단력(judgment) 대신 속도와 볼륨을 최적화할 때 나타나는 기본 결과이며, AI 테스트 생성을 조기에 도입한 팀들이 실제로 무엇을 잡아내는지에 대해 종종 실망하는 이유를 설명해 줍니다.
버그는 필드 내부가 아니라 필드 사이에 존재한다
대부분의 AI 생성 테스트는 필드 수준의 변이(field-level mutations)입니다. 즉, 하나의 필드를 가져와서, 그것을 무효하게 만들고, API가 이를 거부하는지 확인하는 방식입니다. 금액(amount) 필드 누락, 통화(currency)의 잘못된 타입, 허용된 열거형(enum) 범위를 벗어난 상태 값 등이 이에 해당합니다. 이러한 테스트는 유용하며, 모델은 각 테스트가 고립된 단일 필드만을 이해하면 되기 때문에 쉽게 생성할 수 있습니다.
실제로 프로덕션에 도달하는 버그는 그렇게 단순한 경우가 드뭅니다. 버그는 개별적으로는 유효한 여러 필드가 아무도 예상하지 못한 상태로 결합될 때 나타납니다. 예를 들어, 이미 환불된 트랜잭션에 대해 환불을 요청하거나, 통화 변환(currency conversion) 후에 할인 코드를 적용하여 계산을 무효화하거나, 두 개의 서로 다른 결제 수단에 걸쳐 재사용된 멱등성 키(idempotency key) 등이 있습니다. 관련된 모든 필드는 각각의 검증(validation)을 통과합니다. 실패는 오직 필드들이 상호작용하는 방식에서만 존재합니다.
이러한 조합을 조사하는 테스트를 생성하려면 지식(knowledge)보다 더 많은 판단력(judgment)이 필요합니다. 모델은 API가 무엇인지, 유효한 요청이 어떻게 생겼는지를 알아야 합니다. 하지만 결제 엔드포인트의 실제 위험이 금액(amount), 환불 상태(refund_status), 결제 수단(payment_method) 중 어느 하나가 아니라 이들 사이의 상호작용에 있다는 것을 알기 위해서는 완전히 다른 무언가가 필요합니다.
왜 더 많은 프롬프팅(Prompting)도 이를 해결하지 못하는가
본능적인 해결책은 더 나은 프롬프팅 (Prompting)입니다. 더 많은 컨텍스트 (Context), 더 많은 예시, 그리고 무엇을 다루어야 하는지에 대한 더 명시적인 지침을 추가하는 것입니다. 이는 어느 정도 도움이 됩니다. 프롬프팅은 필드 (Field) 수준에서 테스트를 더 철저하게 만듭니다. 하지만 모델이 필드 간에 추론 (Reasoning)하도록 신뢰성 있게 만들지는 못합니다.
그 이유는 문구의 문제라기보다 구조적인 문제입니다. 한 번에 하나의 필드씩 테스트를 생성하는 모델은, 별도로 테스트한 두 필드가 결합하여 문제를 형성할 수 있다는 점을 인지할 자연스러운 이유가 없습니다. 동일한 접근 방식을 더 강하게 밀어붙이는 것은 다른 종류의 테스트가 아니라, 동일한 종류의 테스트를 더 많이 만들어낼 뿐입니다.
무엇이 실제로 격차를 줄이는가
효과적인 해결책은 테스트 생성을 하나의 문제가 아닌 두 개의 별개 문제로 취급하는 것입니다. 첫 번째 문제는 무엇을 왜 테스트해야 하는지 결정하는 것이며, 이는 판단 (Judgment)의 문제입니다. 두 번째는 실제로 실행 가능한 테스트를 작성하는 것이며, 이는 기계적인 (Mechanical) 문제입니다. 이 둘을 혼동하는 것이 양과 질이 서로 어긋나게 되는 이유 중 하나입니다. "유효한 테스트를 생성하라"는 것에 최적화된 시스템은 영원히 유효하지만 얕은 (Shallow) 테스트만을 계속해서 생성할 것입니다.
이 둘을 분리한다는 것은, 판단 레이어 (Judgment layer)가 주의 깊은 QA 엔지니어가 테스트할 가치가 있다고 표시할 만한 것들(필드별 생성 방식으로는 결코 도달할 수 없는 필드 간 교차 케이스를 포함하여)을 전문적으로 학습할 수 있게 하는 동시에, 별도의 레이어가 그 판단을 실제 코드로 변환하는 역할을 수행함을 의미합니다. 또한 이곳은 모델의 크기보다 학습 데이터 (Training data)가 더 중요한 지점이기도 합니다. 인간 검토자가 수락, 거부 또는 재작성한 테스트는 구문적으로 유효한 API 호출의 또 다른 백만 개 예시보다 훨씬 더 강력한 신호 (Signal)가 됩니다.
이것이 지금 왜 중요한가
AI 테스트 생성이 빨라짐에 따라, 얼마나 많은 테스트가 생성되는지로 성공을 측정하려는 유혹에 빠지기 쉽습니다. 하지만 그 숫자는 실제로 중요한 버그가 잡힐지 여부에 대해 거의 아무것도 알려주지 않습니다. AI 기반이든 아니든, 테스트 도구를 평가하는 모든 팀에게 더 유용한 질문은, 단지 한 번에 하나의 필드에서 버그를 찾을 수 있는지 여부가 아니라, 두세 개의 필드가 어떻게 상호작용하는지에 따라 발생하는 버그를 찾을 수 있는지 여부입니다.
이러한 차이점 이면에 있는 아키텍처, 즉 판단(judgment)과 실행(execution)이 실제로는 어떻게 분리되는지, 그리고 그 판단의 근거가 되는 데이터가 실제로 어떤 모습인지에 대해 더 자세히 알고 싶다면, KushoAI의 백서인 Building Adaptive Coverage Systems for API Testing,에서 모든 내용을 다루고 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기