AI Agents · Pelajaran

Meniru Panggilan LLM dalam Pengujian

unittest.mock, fixture pytest, serta merekam dan memutar ulang respons LLM.

Pelajaran 2 dari 413 langkah

Meniru Panggilan LLM dalam Pengujian adalah pelajaran AI Agents gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Agents, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Agents mencakup 4 pelajaran total.

Apa Itu Pembuatan Tiruan?

Pembuatan tiruan menggantikan fungsi atau objek nyata dengan versi palsu yang mengembalikan respons terkontrol. Dalam pengujian agen, kita membuat tiruan untuk panggilan API LLM agar pengujian berjalan seketika, tidak memerlukan biaya, dan menghasilkan hasil yang dapat diprediksi.

Modul Python unittest.mock adalah alat standar untuk keperluan ini.

Dasar-dasar unittest.mock.patch()

unittest.mock.patch(target) menggantikan objek bernama untuk sementara selama pengujian berlangsung. target adalah string bertitik yang menunjuk ke objek sebagaimana objek tersebut diimpor dalam modul yang sedang diuji.

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

Menggunakan patch sebagai Dekorator dalam pytest

Saat digunakan sebagai dekorator dengan pytest, @patch() menyisipkan tiruan sebagai parameter fungsi. Tiruan tersebut otomatis dihapus setelah pengujian selesai.

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()

Membangun Respons Tiruan yang Dapat Digunakan Kembali

Membangun objek respons tiruan secara manual membutuhkan banyak kode. Buat fungsi pembantu untuk membangun objek tiruan dengan struktur yang benar dan sesuai dengan bentuk respons SDK 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)

Membuat Tiruan untuk Panggilan Alat dalam Respons

Saat menguji logika pemanggilan alat milik agen, respons tiruan harus menyertakan bidang tool_calls dengan struktur yang benar agar kode penguraian agen dapat memprosesnya dengan tepat.

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)

Fixture pytest untuk Pembuatan Tiruan

Fixture pytest memungkinkan Anda mendefinisikan kode penyiapan yang dapat digunakan kembali. Buat fixture yang menerapkan patch pada klien LLM dan menyediakannya untuk setiap pengujian yang memintanya — tidak perlu mengulang kode.

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()

Fixture mocker dari pytest-mock

pytest-mock menyediakan fixture mocker yang menyederhanakan penerapan patch. Fixture ini otomatis membersihkan tiruan dan menyediakan sintaks yang lebih rapi daripada unittest.mock.patch mentah.

# 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

Merekam dan Memutar Ulang dengan vcr.py

vcrpy merekam interaksi HTTP nyata ke dalam berkas 'kaset' pada proses pertama, lalu memutarnya ulang pada proses-proses berikutnya. Cara ini ideal untuk menguji kode yang menggunakan API HTTP mentah, bukan 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

Memastikan Tiruan Dipanggil dengan Benar

Setelah pengujian selesai, pastikan tiruan dipanggil dengan argumen yang tepat. Hal ini dapat menemukan kesalahan ketika agen mengirim model yang salah, parameter yang hilang, atau pesan yang keliru.

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'

Mensimulasikan Kesalahan API dalam Pengujian

Uji cara agen Anda menangani kegagalan LLM dengan mengonfigurasi tiruan agar memunculkan pengecualian. Dengan demikian, Anda dapat memverifikasi penanganan kesalahan dan logika percobaan ulang tanpa menyebabkan kegagalan API yang nyata.

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

Mengatur Fixture Tiruan dalam conftest.py

Tempatkan fixture bersama di conftest.py pada akar direktori pengujian Anda. pytest otomatis menemukan berkas ini dan menyediakan fixture untuk semua berkas pengujian tanpa perlu mengimpornya.

# 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

Uji Pemahaman: Pembuatan Tiruan untuk Panggilan LLM

Uji pemahaman Anda tentang teknik pembuatan tiruan untuk pengujian agen.

Ringkasan: Pembuatan Tiruan untuk Panggilan LLM dalam Pengujian

Sekarang Anda memiliki alat untuk menulis pengujian unit agen yang cepat dan andal:

  • Gunakan unittest.mock.patch() untuk mengganti klien LLM dengan tiruan
  • Bangun pembantu respons tiruan yang dapat digunakan kembali dan sesuai dengan struktur respons SDK
  • Buat tiruan untuk panggilan alat dengan bidang tool_calls yang terstruktur dengan benar
  • Gunakan fixture pytest dan conftest.py untuk berbagi tiruan di antara pengujian
  • Gunakan pytest-mock untuk sintaks yang lebih rapi
  • Gunakan vcrpy untuk merekam dan memutar ulang interaksi HTTP nyata

Tiruan adalah dasar dari rangkaian pengujian agen yang cepat dan mudah dipelihara.

Gratis untuk memulai

Belajar AI Agents dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
60
Pelajaran
239

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Meniru Panggilan LLM dalam Pengujian” gratis?

Ya — teks lengkap “Meniru Panggilan LLM dalam Pengujian” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Agents, upgrade ke CoddyKit PRO. Kursus AI Agents mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Meniru Panggilan LLM dalam Pengujian”?

unittest.mock, fixture pytest, serta merekam dan memutar ulang respons LLM. Kamu berlatih AI Agents dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai AI Agents?

Tidak diperlukan pengalaman sebelumnya. AI Agents di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Meniru Panggilan LLM dalam Pengujian” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Agents ini?

Ya. Setiap pelajaran AI Agents menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Mengapa Pengujian Agen Berbeda
  2. Meniru Panggilan LLM dalam Pengujian
  3. Pengujian Agen Berbasis Assertion
  4. Pengujian Integrasi untuk Pipeline Agen
← Kembali ke AI Agents