에이전트 테스트가 다른 이유
비결정성, LLM 비용, 일반 단위 테스트만으로 부족한 이유를 알아봅니다.
에이전트 테스트가 다른 이유은(는) CoddyKit의 무료 AI Agents 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Agents 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.
소프트웨어 테스트와 에이전트 테스트
전통적인 소프트웨어는 결정적입니다. 같은 입력을 주면 같은 출력을 얻습니다. 단위 테스트는 이 특성에 의존해 예상되는 정확한 값을 검증합니다.
인공지능 에이전트는 이러한 가정을 깨뜨립니다. 같은 프롬프트도 실행할 때마다 다른 출력을 만들 수 있으므로, 일반적인 테스트 방식만으로는 충분하지 않습니다.
비결정성: 같은 입력, 다른 출력
LLM은 본질적으로 확률적입니다. temperature 매개변수는 무작위성을 제어하지만, temperature=0인 경우에도 모델 버전이나 인프라 변경에 따라 출력이 달라질 수 있습니다.
따라서 오늘 통과한 에이전트 테스트가 코드 변경 없이도 내일 실패할 수 있습니다.
import openai
client = openai.OpenAI(api_key='YOUR_API_KEY')
# Same prompt, potentially different outputs each run
for i in range(3):
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': 'Name a planet.'}],
temperature=0.9 # High randomness
)
print(f'Run {i+1}: {response.choices[0].message.content}')
# Run 1: Mars
# Run 2: Jupiter
# Run 3: Saturn비용 문제: 실제 LLM 호출은 비쌉니다
OpenAI 또는 앤트로픽에 실제 응용 프로그램 인터페이스 호출을 보내는 테스트 모음을 실행하면 한 번 실행할 때마다 몇 달러가 들 수 있습니다. 100개의 테스트를 10번 반복 실행하는 지속적 통합 파이프라인은 한 달에 수백 달러가 들 수 있습니다.
따라서 단위 테스트를 실행하는 것과 같은 방식으로 에이전트 테스트를 실행하기는 어렵습니다. 비용을 제어할 전략이 필요합니다.
# A test that calls the real API costs tokens every run
# 100 tests x 500 tokens each x 10 CI runs/day = 500,000 tokens/day
# At $0.15/1M tokens (gpt-4o-mini): ~$0.075/day = ~$27/year for a tiny suite
# For gpt-4o: 15x more expensive = ~$400/year
# This is why mocking and recording API responses is essential
print('Real API calls in tests = expensive and slow')
print('Solution: Mock or record LLM responses in unit tests')
print('Reserve real calls for scheduled integration tests')지연 시간 문제
실제 LLM 응용 프로그램 인터페이스 호출은 일반적으로 2~20초가 걸립니다. 테스트가 50개라면 실행에 100~1,000초가 걸립니다. 이는 개발 생산성을 떨어뜨립니다. 빠른 피드백은 좋은 테스트의 핵심 가치입니다.
LLM 호출을 모의 처리하면 테스트가 밀리초 단위로 실행됩니다.
import time
# Simulating what a test suite looks like with real vs mocked calls
num_tests = 50
# Real API calls
real_time = num_tests * 5 # avg 5 seconds per call
print(f'With real API calls: {real_time}s = {real_time/60:.1f} minutes')
# Mocked calls
mock_time = num_tests * 0.001 # <1ms per mock
print(f'With mocked calls: {mock_time:.3f}s = nearly instant')
# Conclusion: mock in unit tests, use real calls in integration tests에이전트 테스트의 외부 종속성
에이전트는 검색 인터페이스, 데이터베이스, 파일 시스템, 웹 스크래퍼와 같은 외부 도구를 자주 호출합니다. 테스트에서 이러한 종속성은 다음과 같은 문제가 있을 수 있습니다.
- 사용할 수 없음(네트워크 중단, 인터페이스 작동 중단)
- 실행할 때마다 다른 데이터를 반환함
- 지속적 통합 파이프라인을 차단하는 요청 빈도 제한이 있음
단위 테스트에서는 이러한 종속성을 제어하거나 모의 처리해야 합니다.
# An agent might call multiple external services
# Each is a potential test failure point
def agent_pipeline(query: str) -> str:
search_results = search_web(query) # External: Tavily/Serper API
documents = fetch_documents(search_results) # External: HTTP calls
answer = llm_summarize(documents) # External: OpenAI API
saved = database_store(answer) # External: PostgreSQL
return answer
# In unit tests: mock ALL of these
# In integration tests: use sandboxed versions of real services
print('Each external call is a test reliability risk')일반 단위 테스트의 가정
pytest와 같은 일반 단위 테스트 프레임워크는 다음을 가정합니다.
- 테스트가 빠르게 실행됨(밀리초 단위)
- 테스트가 결정적임
- 테스트에 외부 부작용이 없음
- 테스트를 어떤 순서로든 실행할 수 있음
이러한 가정을 고려해 명시적으로 설계하지 않으면 에이전트 테스트는 네 가지 가정을 모두 위반합니다.
# Standard unit test — works perfectly for deterministic code
def add(a, b):
return a + b
def test_add():
assert add(2, 3) == 5 # Always passes — deterministic
# Agent 'unit test' that calls a real LLM — problematic
# def test_agent_answers_question():
# response = agent.run('What is 2+2?')
# assert response == '4' # Might return 'The answer is 4' or 'Four'
print('Exact string matching fails for LLM outputs')
print('Need structural or semantic assertions instead')에이전트를 위한 테스트 피라미드
에이전트를 위한 실용적인 테스트 전략은 피라미드 형태를 따릅니다.
- 단위 테스트(많고 빠름): LLM 호출을 모의 처리하면서 개별 도구와 함수를 테스트합니다.
- 통합 테스트(더 적고 느림): 격리된 서비스로 에이전트 파이프라인을 처음부터 끝까지 테스트합니다.
- 평가 테스트(드물고 비용이 큼): 실제 LLM 호출과 사람처럼 평가하는 점수 산정으로 출력 품질을 테스트합니다.
구조적 검증과 의미적 검증
에이전트 테스트에서는 정확한 문자열을 일치시키는 대신 구조적 검증(에이전트가 올바른 도구를 호출했는가?)이나 의미적 확인(출력에 관련 개념이 포함되어 있는가?)을 사용해야 합니다.
# Fragile: exact string match
# assert response.content == 'The capital of France is Paris.'
# Better: structural assertion
# assert response.tool_calls[0]['function']['name'] == 'search_web'
# Better: semantic check
def test_capital_in_response(response_text: str) -> bool:
key_words = ['paris', 'france', 'capital']
lower = response_text.lower()
return all(word in lower for word in key_words)
response = 'Paris is the capital city of France.'
print(test_capital_in_response(response)) # True평가 도구와 LLM 심사자 방식
품질 평가를 위해 업계에서는 LLM 심사자 방식을 사용합니다. 두 번째 LLM에 에이전트의 출력을 평가하도록 요청하는 방식입니다. DeepEval과 RAGAS와 같은 프레임워크가 이 방식을 자동화합니다.
이 방식은 일상적인 지속적 통합이 아니라 비용이 많이 드는 평가 실행에 사용합니다.
import openai
client = openai.OpenAI(api_key='YOUR_API_KEY')
def llm_judge(question: str, answer: str) -> dict:
prompt = f'Question: {question}\nAnswer: {answer}\nRate the answer 1-5 for accuracy. Reply with only a number.'
response = client.chat.completions.create(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}]
)
score = int(response.choices[0].message.content.strip())
return {'score': score, 'pass': score >= 4}
# result = llm_judge('What is the capital of France?', 'Paris')
# print(result) # {'score': 5, 'pass': True}에이전트 회귀 테스트
프롬프트를 업데이트하거나 에이전트 로직을 변경할 때 회귀 테스트는 기존 동작이 손상되지 않았는지 확인합니다. 기준 예시(입력 → 예상 구조)를 기록하고 모든 커밋에서 자동으로 실행하세요.
# golden_examples.py
GOLDEN_EXAMPLES = [
{
'input': 'Search for the weather in Paris',
'expected_tool': 'get_weather',
'expected_args': {'city': 'Paris'}
},
{
'input': 'Calculate 15% tip on $45',
'expected_tool': 'calculate',
'expected_args': {'expression': '45 * 0.15'}
}
]
def run_regressions(agent, examples: list) -> int:
failures = 0
for ex in examples:
result = agent.plan(ex['input']) # mocked LLM
if result['tool'] != ex['expected_tool']:
print(f'FAIL: expected {ex["expected_tool"]}, got {result["tool"]}')
failures += 1
return failures
# --- demo: a stub agent whose .plan() mimics an LLM's tool choice ---
class _StubAgent:
def plan(self, text):
if 'weather' in text.lower():
return {'tool': 'get_weather'}
if 'tip' in text.lower() or 'calculate' in text.lower():
return {'tool': 'wrong_tool'} # simulate a regression
return {'tool': 'unknown'}
failures = run_regressions(_StubAgent(), GOLDEN_EXAMPLES)
print(f'{failures} of {len(GOLDEN_EXAMPLES)} golden examples failed')
기본 에이전트 테스트 파일 설정
다음은 에이전트를 위한 최소한의 파이테스트 테스트 파일 구조입니다. 빠른 단위 테스트(모의 객체 사용)와 느린 통합 테스트(실제 호출 사용)를 분리하므로 필요한 테스트만 실행할 수 있습니다.
# tests/test_agent.py
import pytest
# Fast unit tests — run on every commit
class TestAgentTools:
def test_tool_returns_dict(self, mock_llm):
result = my_tool(query='test')
assert isinstance(result, dict)
assert 'data' in result
def test_agent_selects_correct_tool(self, mock_llm):
response = agent.run('Search for Python tutorials')
assert response['tool_used'] == 'web_search'
# Slow integration tests — run nightly or on release
@pytest.mark.integration
class TestAgentIntegration:
def test_full_pipeline_with_real_api(self):
# Uses real OpenAI + sandboxed services
result = agent.run('Summarize the Python docs')
assert len(result['answer']) > 50지식 확인: 에이전트 테스트가 다른 이유
인공지능 에이전트 테스트의 고유한 과제에 대한 이해도를 확인해 보세요.
복습: 에이전트 검사가 다른 이유
AI 에이전트 검사는 일반적인 단위 검사와는 다른 관점이 필요합니다.
- 비결정성: 동일한 입력에서도 서로 다른 유효한 출력이 생성될 수 있습니다
- 비용: 실제 LLM 호출은 비용이 많이 들므로 단위 검사에서는 모의 객체를 사용해야 합니다
- 지연 시간: 실제 API 호출은 수 초가 걸리지만 모의 객체는 밀리초 단위로 실행됩니다
- 외부 의존성: 검사에서는 도구와 API를 제어해야 합니다
- 단언: 정확한 문자열 일치가 아니라 구조적·의미적 검사를 사용해야 합니다
검사 피라미드를 사용하십시오. 모의 객체를 사용하는 저렴한 단위 검사는 많이 작성하고, 실제 호출을 사용하는 비용이 큰 통합 검사는 적게 작성하십시오.
자주 묻는 질문
“에이전트 테스트가 다른 이유” 강의는 무료인가요?
네 — “에이전트 테스트가 다른 이유” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Agents 강의 전체를 잠금 해제할 수 있습니다. AI Agents 강의에는 총 4개의 강의가 포함되어 있습니다.
“에이전트 테스트가 다른 이유”에서 뭘 배우나요?
비결정성, LLM 비용, 일반 단위 테스트만으로 부족한 이유를 알아봅니다. 브라우저에서 직접 실행하는 실습 코드로 AI Agents을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
AI Agents을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 AI Agents은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“에이전트 테스트가 다른 이유” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 AI Agents 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 AI Agents 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 에이전트 테스트가 다른 이유
- 테스트에서 LLM 호출 모의 처리
- 단정문 기반 에이전트 테스트
- 에이전트 파이프라인의 통합 테스트