AI-agenter · Lektion

Varför agenttestning skiljer sig

Icke-determinism, LLM-kostnader och varför vanliga enhetstester inte räcker.

Lektion 1 av 413 steg

Varför agenttestning skiljer sig är en gratis lektion i AI-agenter på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för AI-agenter, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i AI-agenter innehåller totalt 4 lektioner.

Testa programvara kontra testa agenter

Traditionell programvara är deterministisk: samma indata ger samma utdata. Enhetstester bygger på denna egenskap för att kontrollera exakta förväntade värden.

AI-agenter bryter mot detta antagande. Samma prompt kan ge olika utdata vid varje körning, vilket gör att vanliga testmetoder inte räcker på egen hand.

Icke-determinism: samma indata, olika utdata

LLM:er är av naturen probabilistiska. Parametern temperature styr slumpmässigheten – även vid temperature=0 kan utdata variera mellan modellversioner eller förändringar i infrastrukturen.

Det innebär att ett agenttest som klarar sig i dag kan misslyckas i morgon utan någon kodändring.

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

Kostnadsproblemet: riktiga LLM-anrop är dyra

Att köra en testsamling som gör riktiga API-anrop till OpenAI eller Anthropic kan kosta flera dollar per körning. En CI-pipeline som kör 100 tester × 10 iterationer kan kosta hundratals dollar i månaden.

Det gör det opraktiskt att köra agenttester på samma sätt som enhetstester – ni behöver strategier för att kontrollera kostnaderna.

# 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')

Fördröjningsproblemet

Riktiga LLM-API-anrop tar vanligtvis 2–20 sekunder. En testsamling med 50 tester skulle ta 100–1 000 sekunder att köra. Det försämrar utvecklarnas produktivitet – snabb återkoppling är ett centralt värde i bra tester.

Genom att simulera LLM-anrop körs tester på millisekunder.

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

Externa beroenden i agenttester

Agenter anropar ofta externa verktyg: sök-API:er, databaser, filsystem och webbskrapare. I tester kan dessa beroenden:

  • vara otillgängliga (nätverksavbrott eller API-avbrott)
  • returnera olika data vid varje körning
  • ha hastighetsbegränsningar som blockerar CI-pipelines

Dessa beroenden måste kontrolleras eller simuleras i enhetstester.

# 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')

Vad vanliga enhetstester förutsätter

Vanliga ramverk för enhetstester, som pytest, förutsätter att:

  • tester är snabba (millisekunder)
  • tester är deterministiska
  • tester inte har några externa sidoeffekter
  • tester kan köras i valfri ordning

Agenttester bryter mot alla fyra antaganden om ni inte uttryckligen utformar dem med hänsyn till detta.

# 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')

Testpyramiden för agenter

En praktisk teststrategi för agenter följer en pyramid:

  • Enhetstester (många, snabba): Testa enskilda verktyg och funktioner med simulerade LLM-anrop
  • Integrationstester (färre, långsammare): Testa agentens pipeline från början till slut med isolerade tjänster
  • Utvärderingstester (sällsynta, dyra): Testa utdatakvalitet med riktiga LLM-anrop och bedömning på mänskligt sätt

Strukturella kontra semantiska påståenden

I stället för exakt strängmatchning bör agenttester använda strukturella påståenden (anropade agenten rätt verktyg?) eller semantiska kontroller (innehåller utdatan det relevanta konceptet?).

# 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

Utvärderingsramverk och LLM-as-Judge

För kvalitetsutvärdering använder branschen LLM-as-judge: be en andra LLM att bedöma agentens utdata. Ramverk som DeepEval och RAGAS automatiserar detta mönster.

Detta är avsett för dyra utvärderingskörningar, inte för rutinmässig CI.

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}

Regressionstestning för agenter

När ni uppdaterar en prompt eller ändrar agentens logik verifierar regressionstester att ni inte har förstört befintligt beteende. Spara gyllene exempel (indata → förväntad struktur) och kör dem automatiskt vid varje commit.

# 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')

Konfigurera en enkel testfil för en agent

Här är en minimal struktur för en pytest-testfil för en agent. Den skiljer snabba enhetstester (med simulerade anrop) från långsamma integrationstester (med riktiga anrop), så att ni kan köra bara de tester ni behöver.

# 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

Kunskapskontroll: Varför agenttestning skiljer sig

Testa er förståelse av de unika utmaningarna med att testa AI-agenter.

Sammanfattning: Varför testning av agenter skiljer sig åt

Testning av AI-agenter kräver ett annat tankesätt än vanlig enhetstestning:

  • Icke-determinism: Samma indata kan ge olika giltiga utdata
  • Kostnad: Riktiga LLM-anrop är dyra — mocka dem i enhetstester
  • Fördröjning: Riktiga API-anrop tar sekunder — mock-anrop körs på millisekunder
  • Externa beroenden: Verktyg och API:er måste kontrolleras i tester
  • Verifieringar: Använd strukturella och semantiska kontroller i stället för exakt strängmatchning

Använd en testpyramid: många billiga enhetstester med mockar och färre dyra integrationstester med riktiga anrop.

Gratis att börja

Lär dig AI-agenter med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
60
Lektioner
239

Vanliga frågor

Är lektionen ”Varför agenttestning skiljer sig” gratis?

Ja – hela texten till ”Varför agenttestning skiljer sig” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i AI-agenter, kan Ni uppgradera till CoddyKit PRO. Kursen i AI-agenter innehåller totalt 4 lektioner.

Vad lär jag mig i ”Varför agenttestning skiljer sig”?

Icke-determinism, LLM-kostnader och varför vanliga enhetstester inte räcker. Ni övar på AI-agenter med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig AI-agenter?

Du behöver inga förkunskaper. Utbildningen i AI-agenter på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.

Hur lång tid tar lektionen ”Varför agenttestning skiljer sig”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här AI-agenter-lektionen?

Ja. Varje AI-agenter-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Varför agenttestning skiljer sig
  2. Mocka LLM-anrop i tester
  3. Assertions-baserad agenttestning
  4. Integrationstester för agentpipelines
← Tillbaka till AI-agenter