3.3.1.2 테스트 케이스의 독립성 보장

3.3.1.2 테스트 케이스의 독립성 보장

단일 책임 원칙(Single Responsibility Principle)에 따라 정답지(Ground Truth)를 원자적(Atomic) 단위로 분해했다면, 그 분해된 각각의 테스트 케이스(Test Case)들은 서로 어떠한 상태(State)나 결과값도 공유해서는 안 된다. 즉, N번째 테스트 케이스의 성공 또는 실패 여부가 (N+1)번째 테스트 케이스의 실행이나 검증 결과에 논리적, 데이터적 영향을 미치는 ’결합(Coupling)’은 결정론적 오라클 시스템에서 철저하게 배제되어야 한다.

1. 테스트 간 상태 전이(State Bleeding)의 위험성

기존 소프트웨어 공학에서 전역 변수(Global Variable) 상태가 단위 테스트를 오염시키는 것과 마찬가지로, AI 프롬프팅 및 오라클 평가 파이프라인에서도 **상태 전이(State Bleeding)**는 치명적인 결과를 초래한다.

  • 안티 패턴(Anti-Pattern):
  • Test Case 1: 사용자 프로필에서 “나이“를 추출하라. (정답: 35)
  • Test Case 2: TC 1에서 추출한 나이를 바탕으로 대출 가능 여부를 검증하라. (정답: 가능)
  • 문제점: 만약 TC 1에서 LLM의 환각이나 파싱 에러로 인해 나이 추출에 실패(Fail)했다면, TC 2는 LLM의 로직 판단 능력이 정상임에도 불구하고 필수 입력값이 없어 연쇄적으로 실패(Cascade Fail)하게 된다. 이 경우 뼈대(Framework)를 제공하는 오라클은 TC 2의 실패 원인이 ‘LLM의 추론 능력 부족’ 때문인지 ‘단순 입력값 누락’ 때문인지 정확하게 격리하여 보고할 수 없다.

2. 모의 객체(Mocking)를 통한 인과관계의 단절

Test Case 1의 출력값이 Test Case 2의 입력값으로 이어지는 비즈니스 워크플로우를 테스트해야 할 때, 오라클 시스템은 반드시 중간 과정을 모의 객체(Mock)로 단절시켜야 한다.

  • 파이프라인 검증 시, TC 2를 실행할 때는 TC 1의 실제 LLM 출력 결과를 기다리지 않는다.
  • 대신, TC 2의 프롬프트와 오라클 검증 로직에는 “가설적으로 TC 1이 완벽하게 35라는 값을 반환했다고 가정할 때(Mocking Data Injection)“라는 확정된 상태(Given State)를 하드코딩하여 주입한다.

이를 통해 TC 2는 전적으로 “LLM이 35라는 주어진 온전한 데이터를 가지고 대출 가능 여부를 판단할 수 있는가?“라는 단일 역량(Single Capability)만을 철저하고 독립적으로 뜯어볼 수 있게 된다.

3. 병렬 실행(Parallel Execution) 가능성의 확보

테스트 케이스들을 상호 독립적으로 설계해야 하는 또 다른 엔지니어링적 이유는 파이프라인의 **속도(Latency)**와 관련이 깊다.

LLM에 대한 테스트는 전통적인 코드의 유닛 테스트보다 수십 배에서 수백 배의 API 호출 시간(I/O Bound)을 소모한다. 테스트 케이스 간의 의존성(Dependency)이 존재하면, 이 파이프라인은 필연적으로 절차적(Sequential)으로 실행되어야 하며, 데이터셋의 규모가 커질수록 CI/CD 브랜치 병합(Merge) 시간은 지옥처럼 길어진다.

반대로 모든 Golden Dataset의 요소들이 완벽한 독립성을 보장받는다면, 1만 개의 테스트 케이스도 컴퓨팅 리소스가 허락하는 한 1만 개의 스레드(Thread)로 완벽하게 쪼개어져 비동기적(Asynchronous) 병렬 실행이 가능해진다.

독립성이 보장된 정답지는 각기 다른 진단 키트와 같다. 하나를 검사하기 위해 다른 하나의 결과를 기다릴 필요도 없고, 하나의 실패가 다른 영역의 검증을 오염시키지도 않는다. 오직 이 철저한 격리(Isolation)만이, 변덕스러운 AI의 수백 가지 능력을 개별적으로 안전하게 타격하고 평가할 수 있는 유일한 공학적 수단이다.