Por que testar agentes é diferente
Não determinismo, custo de LLM e por que os testes unitários padrão são insuficientes.
Por que testar agentes é diferente é uma aula grátis de AI Agents no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de AI Agents, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de AI Agents inclui 4 aulas no total.
Testando software em comparação com agentes
O software tradicional é determinístico: forneça a mesma entrada e obtenha a mesma saída. Os testes unitários dependem dessa propriedade para verificar valores exatos esperados.
Os agentes de IA quebram essa suposição. O mesmo comando pode produzir saídas diferentes a cada execução, tornando as abordagens padrão de teste insuficientes por si só.
Não determinismo: mesma entrada, saída diferente
LLMs são probabilísticos por natureza. O parâmetro temperature controla a aleatoriedade — mesmo em temperature=0, as saídas podem variar entre versões do modelo ou mudanças na infraestrutura.
Isso significa que um teste do agente aprovado hoje pode falhar amanhã sem nenhuma alteração no código.
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: SaturnO problema do custo: chamadas reais a LLM são caras
Executar uma suíte de testes que faz chamadas reais de API para OpenAI ou Anthropic pode custar dólares por execução. Um fluxo de CI que executa 100 testes × 10 iterações poderia custar centenas de dólares por mês.
Isso torna impraticável executar testes de agentes da mesma forma que testes unitários — são necessárias estratégias para controlar os custos.
# 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')O problema da latência
Chamadas reais às APIs de LLM normalmente levam de 2 a 20 segundos. Uma suíte com 50 testes levaria de 100 a 1.000 segundos para ser executada. Isso prejudica a produtividade dos desenvolvedores — um retorno rápido é um valor essencial de bons testes.
Simular chamadas de LLM faz os testes serem executados em milissegundos.
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 testsDependências externas nos testes de agentes
Os agentes frequentemente chamam ferramentas externas: APIs de pesquisa, bancos de dados, sistemas de arquivos e ferramentas de raspagem da web. Nos testes, essas dependências podem:
- Estar indisponíveis (interrupção da rede, indisponibilidade da API)
- Retornar dados diferentes a cada execução
- Ter limites de frequência que bloqueiam os fluxos de CI
Essas dependências precisam ser controladas ou simuladas nos testes unitários.
# 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')O que os testes unitários padrão pressupõem
Estruturas padrão de testes unitários, como pytest, pressupõem:
- Os testes são rápidos (milissegundos)
- Os testes são determinísticos
- Os testes não têm efeitos colaterais externos
- Os testes podem ser executados em qualquer ordem
Os testes de agentes violam essas quatro suposições, a menos que você os projete explicitamente levando isso em conta.
# 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')A pirâmide de testes para agentes
Uma estratégia prática de testes para agentes segue uma pirâmide:
- Testes unitários (muitos e rápidos): teste ferramentas e funções individuais com chamadas de LLM simuladas
- Testes de integração (menos numerosos e mais lentos): teste o fluxo do agente de ponta a ponta com serviços em ambiente isolado
- Testes de avaliação (raros e caros): teste a qualidade da saída com chamadas reais de LLM e pontuação semelhante à humana
Asserções estruturais vs. semânticas
Em vez de comparar cadeias de caracteres exatas, os testes de agentes devem usar asserções estruturais (o agente chamou a ferramenta correta?) ou verificações semânticas (a saída contém o conceito relevante?).
# 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)) # TrueEstruturas de avaliação e LLM como avaliador
Para avaliar a qualidade, o setor usa o padrão LLM como avaliador: peça a um segundo LLM que avalie a saída do agente. Estruturas como DeepEval e RAGAS automatizam esse padrão.
Isso fica reservado para execuções de avaliação caras, não para a CI de rotina.
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}Testes de regressão para agentes
Quando você atualiza uma instrução ou altera a lógica do agente, os testes de regressão verificam se não interrompeu o comportamento existente. Registre exemplos de referência (entrada → estrutura esperada) e execute-os automaticamente a cada alteração confirmada.
# 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')
Configurando um arquivo básico de testes de agente
Aqui está uma estrutura mínima de arquivo de testes pytest para um agente. Ela separa testes unitários rápidos (com simulações) de testes de integração lentos (com chamadas reais), permitindo executar apenas o que você precisa.
# 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']) > 50Verificação de conhecimentos: por que os testes de agentes são diferentes
Teste sua compreensão dos desafios específicos dos testes de agentes de IA.
Recapitulação: por que testar agentes é diferente
Testar agentes de IA exige uma mentalidade diferente da usada em testes unitários tradicionais:
- Não determinismo: a mesma entrada pode produzir saídas válidas diferentes
- Custo: chamadas reais a LLM são caras — use objetos simulados nos testes unitários
- Latência: chamadas reais à API levam segundos — objetos simulados são executados em milissegundos
- Dependências externas: ferramentas e APIs precisam ser controladas nos testes
- Asserções: use verificações estruturais e semânticas, não correspondência exata de texto
Use uma pirâmide de testes: muitos testes unitários baratos com objetos simulados e menos testes de integração caros com chamadas reais.
Perguntas Frequentes
A aula “Por que testar agentes é diferente” é grátis?
Sim — o texto completo de “Por que testar agentes é diferente” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de AI Agents, atualize para CoddyKit PRO. O curso de AI Agents inclui 4 aulas no total.
O que vou aprender em “Por que testar agentes é diferente”?
Não determinismo, custo de LLM e por que os testes unitários padrão são insuficientes. Você pratica AI Agents com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar AI Agents?
Nenhuma experiência prévia é necessária. AI Agents no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “Por que testar agentes é diferente”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de AI Agents?
Sim. Cada aula de AI Agents inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Por que testar agentes é diferente
- Simulando chamadas de LLM em testes
- Testes de agentes baseados em asserções
- Testes de integração para pipelines de agentes