0Pricing
AI Agents · Aula

Simulando chamadas de LLM em testes

unittest.mock, dispositivos de teste do pytest e gravação/reprodução de respostas de LLM.

Simulando chamadas de LLM em testes é uma aula grátis de AI Agents no CoddyKit. Esta é a aula 2 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.

O que é simulação

A simulação substitui uma função ou objeto real por uma versão falsa que retorna respostas controladas. Nos testes de agentes, simulamos chamadas à API de LLM para que os testes sejam executados instantaneamente, não tenham custo e produzam resultados previsíveis.

O módulo unittest.mock do Python é a ferramenta padrão para isso.

Noções básicas de unittest.mock.patch()

unittest.mock.patch(target) substitui temporariamente o objeto nomeado durante a execução de um teste. O target é uma cadeia de caracteres com pontos que aponta para o objeto conforme ele é importado no módulo sob teste.

from unittest.mock import patch, MagicMock

# The function under test calls openai.chat.completions.create
# We patch it so no real API call is made

def ask_llm(question: str) -> str:
    import openai
    client = openai.OpenAI(api_key='test')
    resp = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': question}]
    )
    return resp.choices[0].message.content

with patch('openai.OpenAI') as mock_client_class:
    mock_instance = MagicMock()
    mock_client_class.return_value = mock_instance
    mock_instance.chat.completions.create.return_value = MagicMock(
        choices=[MagicMock(message=MagicMock(content='Paris'))]
    )
    result = ask_llm('Capital of France?')
    print(result)  # 'Paris' — no API call made

Usando patch como decorador no pytest

Quando usado como decorador com pytest, @patch() injeta o objeto simulado como um parâmetro da função. O objeto simulado é removido automaticamente depois que o teste é concluído.

from unittest.mock import patch, MagicMock
import pytest

# Assume agent.py contains: import openai; client = openai.OpenAI(...)

@patch('agent.openai.OpenAI')
def test_agent_calls_llm(mock_openai_class):
    # Set up the mock chain
    mock_client = MagicMock()
    mock_openai_class.return_value = mock_client
    mock_client.chat.completions.create.return_value = MagicMock(
        choices=[MagicMock(message=MagicMock(content='Paris is the capital of France.'))]
    )

    from agent import ask_llm
    result = ask_llm('What is the capital of France?')

    assert 'Paris' in result
    mock_client.chat.completions.create.assert_called_once()

Criando uma resposta simulada reutilizável

Criar manualmente objetos de resposta simulados é trabalhoso. Crie uma função auxiliar para construir objetos simulados corretamente estruturados, que correspondam ao formato de resposta do SDK da OpenAI.

from unittest.mock import MagicMock

def make_mock_response(content: str, tool_calls: list = None) -> MagicMock:
    message = MagicMock()
    message.content = content
    message.tool_calls = tool_calls or []

    choice = MagicMock()
    choice.message = message
    choice.finish_reason = 'stop' if not tool_calls else 'tool_calls'

    response = MagicMock()
    response.choices = [choice]
    response.usage = MagicMock(total_tokens=42)
    return response

# Usage in tests:
# mock_create.return_value = make_mock_response('Hello!')
# mock_create.return_value = make_mock_response('', tool_calls=[...])

# --- demo ---
response = make_mock_response('The weather in Paris is 18C and sunny.')
print('content:', response.choices[0].message.content)
print('finish_reason:', response.choices[0].finish_reason)
print('total_tokens:', response.usage.total_tokens)

Simulando chamadas de ferramentas em respostas

Ao testar a lógica de chamadas de ferramentas de um agente, a resposta simulada precisa incluir um campo tool_calls estruturado corretamente para que o código de análise do agente possa processá-lo de forma adequada.

import json
from unittest.mock import MagicMock

def make_tool_call_response(tool_name: str, arguments: dict) -> MagicMock:
    tool_call = MagicMock()
    tool_call.id = 'call_abc123'
    tool_call.type = 'function'
    tool_call.function = MagicMock()
    tool_call.function.name = tool_name
    tool_call.function.arguments = json.dumps(arguments)

    message = MagicMock()
    message.content = None
    message.tool_calls = [tool_call]

    response = MagicMock()
    response.choices = [MagicMock(message=message, finish_reason='tool_calls')]
    return response

# mock.return_value = make_tool_call_response('search_web', {'query': 'Python tutorials'})

# --- demo ---
response = make_tool_call_response('search_web', {'query': 'Python tutorials'})
call = response.choices[0].message.tool_calls[0]
print('tool name:', call.function.name)
print('tool arguments:', call.function.arguments)
print('finish_reason:', response.choices[0].finish_reason)

Fixtures do pytest para simulação

As fixtures do pytest permitem definir código de configuração reutilizável. Crie uma fixture que aplique uma simulação ao cliente de LLM e a forneça a qualquer teste que a solicite — sem repetição.

import pytest
from unittest.mock import patch, MagicMock

@pytest.fixture
def mock_openai(make_mock_response):
    with patch('myagent.client.chat.completions.create') as mock_create:
        mock_create.return_value = MagicMock(
            choices=[MagicMock(message=MagicMock(
                content='Default mocked response',
                tool_calls=[]
            ))]
        )
        yield mock_create

# Now any test can use it:
def test_agent_responds(mock_openai):
    from myagent import agent
    result = agent.run('Hello')
    assert result is not None
    mock_openai.assert_called_once()

A fixture mocker do pytest-mock

pytest-mock fornece uma fixture mocker que simplifica a aplicação de simulações. Ela limpa os objetos simulados automaticamente e oferece uma sintaxe mais simples que o uso direto de unittest.mock.patch.

# pip install pytest-mock

# In your test file:
def test_agent_with_mocker(mocker):
    mock_create = mocker.patch('myagent.client.chat.completions.create')
    mock_create.return_value = mocker.MagicMock(
        choices=[mocker.MagicMock(message=mocker.MagicMock(
            content='Mocked answer',
            tool_calls=[]
        ))]
    )

    from myagent import agent
    result = agent.run('What is 2+2?')
    assert 'answer' in result.lower() or '4' in result

    mock_create.assert_called_once()
    # No cleanup needed — mocker handles it

Gravando e reproduzindo com vcr.py

vcrpy grava interações HTTP reais em um arquivo de gravação na primeira execução e depois as reproduz nas execuções seguintes. Isso é ideal para testar código que usa a API HTTP diretamente, em vez de um SDK.

# pip install vcrpy
import vcr
import httpx

@vcr.use_cassette('fixtures/cassettes/openai_chat.yaml')
def test_with_recorded_response():
    # First run: makes a real HTTP call and records it
    # Subsequent runs: uses the recorded cassette (no network, no cost)
    response = httpx.post(
        'https://api.openai.com/v1/chat/completions',
        json={'model': 'gpt-4o-mini', 'messages': [{'role': 'user', 'content': 'Hello'}]},
        headers={'Authorization': 'Bearer YOUR_KEY'}
    )
    data = response.json()
    assert data['choices'][0]['message']['content'] is not None

Verificando se o objeto simulado foi chamado corretamente

Depois de um teste, verifique se o objeto simulado foi chamado com os argumentos corretos. Isso identifica erros em que o agente envia o modelo errado, omite parâmetros ou envia mensagens incorretas.

from unittest.mock import patch, MagicMock, call

@patch('myagent.client.chat.completions.create')
def test_agent_sends_correct_model(mock_create):
    mock_create.return_value = MagicMock(
        choices=[MagicMock(message=MagicMock(content='ok', tool_calls=[]))]
    )

    from myagent import agent
    agent.run('Hello')

    # Verify the mock was called with correct arguments
    mock_create.assert_called_once()
    call_kwargs = mock_create.call_args.kwargs
    assert call_kwargs['model'] == 'gpt-4o-mini'
    assert len(call_kwargs['messages']) >= 1
    assert call_kwargs['messages'][0]['role'] == 'system'

Simulando erros de API nos testes

Teste como seu agente lida com falhas de LLM configurando o objeto simulado para lançar exceções. Isso verifica o tratamento de erros e a lógica de novas tentativas sem causar falhas reais de API.

from unittest.mock import patch
import openai

@patch('myagent.client.chat.completions.create')
def test_agent_handles_rate_limit(mock_create):
    # Simulate a rate limit error
    mock_create.side_effect = openai.RateLimitError(
        message='Rate limit exceeded',
        response=None,
        body=None
    )

    from myagent import agent
    result = agent.run('Hello')

    # Agent should handle this gracefully
    assert result['error'] == 'rate_limit'
    # or
    assert result['retry_after'] is not None

Organizando fixtures de simulação em conftest.py

Coloque as fixtures compartilhadas em conftest.py, na raiz do diretório de testes. O pytest detecta esse arquivo automaticamente e disponibiliza as fixtures para todos os arquivos de teste sem que seja necessário importá-las.

# tests/conftest.py
import pytest
from unittest.mock import patch, MagicMock

@pytest.fixture(autouse=False)
def mock_llm():
    with patch('myagent.client.chat.completions.create') as mock_create:
        mock_create.return_value = MagicMock(
            choices=[MagicMock(message=MagicMock(
                content='Test response',
                tool_calls=[]
            ))]
        )
        yield mock_create

@pytest.fixture
def mock_search_tool():
    with patch('myagent.tools.search_web') as mock_search:
        mock_search.return_value = [{'title': 'Test', 'url': 'https://example.com'}]
        yield mock_search

Verificação de conhecimento: simulando chamadas de LLM

Teste sua compreensão das técnicas de simulação para testes de agentes.

Recapitulação: simulando chamadas de LLM nos testes

Agora você tem as ferramentas necessárias para escrever testes unitários de agentes rápidos e confiáveis:

  • Use unittest.mock.patch() para substituir clientes de LLM por objetos simulados
  • Crie funções auxiliares reutilizáveis para respostas simuladas que correspondam ao formato de resposta do SDK
  • Simule chamadas de ferramentas com campos tool_calls estruturados corretamente
  • Use fixtures do pytest e conftest.py para compartilhar objetos simulados entre os testes
  • Use pytest-mock para obter uma sintaxe mais simples
  • Use vcrpy para gravar e reproduzir interações HTTP reais

Os objetos simulados são a base de uma suíte de testes de agentes rápida e fácil de manter.

Perguntas Frequentes

A aula “Simulando chamadas de LLM em testes” é grátis?

Sim — o texto completo de “Simulando chamadas de LLM em testes” é 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 “Simulando chamadas de LLM em testes”?

unittest.mock, dispositivos de teste do pytest e gravação/reprodução de respostas de LLM. 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 2 de 4.

Quanto tempo leva a aula “Simulando chamadas de LLM em testes”?

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

  1. Por que testar agentes é diferente
  2. Simulando chamadas de LLM em testes
  3. Testes de agentes baseados em asserções
  4. Testes de integração para pipelines de agentes
← Voltar para AI Agents