Skip to content

Integration-Tests

Übersicht

Integration-Tests sind eine spezielle Kategorie von Tests, die echte Aufrufe an externe Dienste durchführen und deren tatsächliche Antworten validieren. Im Gegensatz zu Feature- und Unit-Tests, die externe Abhängigkeiten mocken, verwenden Integration-Tests die realen APIs.

Wann werden Integration-Tests verwendet?

Integration-Tests sind speziell für folgende Szenarien vorgesehen:

  • AI-Service-Integrationen: Tests für Tiro, Varro, Grammaticus, AeliusDonatus
  • Drittanbieter-APIs: Externe Services wie Anthropic Claude, OpenAI, etc.
  • Antwortformat-Validierung: Prüfung echter API-Antwortstrukturen
  • Qualitätsprüfung: Validierung der Qualität generierter Inhalte
  • Regression-Tests: Erkennung von Änderungen nach API-Updates

Unterschied zu anderen Test-Kategorien

KategorieExterne CallsAPI-KostenAusführungZweck
Unit-TestsKeineNeinAutomatischIsolierte Komponenten-Tests
Feature-TestsGemocktNeinAutomatischFeatures aus Nutzersicht
Integration-TestsEchtJaManuell/On-DemandExterne API-Validierung

Speicherorte

Hauptanwendung

tests/Integration/
├── AI/
│   ├── VarroIntegrationTest.php
│   ├── TiroIntegrationTest.php
│   └── GrammaticusIntegrationTest.php
└── ExternalServices/
    └── ThirdPartyAPITest.php

Module

modules/Services/HermeneusAI/tests/Integration/
└── AIServiceIntegrationTest.php

PHPUnit-Konfiguration

In der phpunit.xml ist die Integration-Testsuite separat definiert:

xml
<testsuite name="Integration">
    <directory suffix="Test.php">./tests/Integration</directory>
    <directory suffix="Test.php">./modules/*/*/tests/Integration</directory>
</testsuite>

Wichtig: Diese Testsuite wird NICHT automatisch bei php artisan test ausgeführt!

Test-Ausführung

Alle Integration-Tests

bash
# Via Testsuite
php artisan test --testsuite=Integration

# Via Group-Tag
php artisan test --group=integration

Einzelne Integration-Tests

bash
# Einzelne Datei
php artisan test tests/Integration/AI/VarroIntegrationTest.php

# Einzelnes Modul
php artisan test modules/Services/HermeneusAI/tests/Integration/

Mit Test-Runner

bash
# Mit Smart-Check und Setup
php artisan test:run --testsuite=Integration

# Mit frischer Datenbank
php artisan test:run --fresh --testsuite=Integration

Best Practices

1. Group-Tagging

Alle Integration-Tests sollten mit @group integration getaggt werden:

php
<?php

use function Pest\Laravel\{postJson};

test('varro validiert echte glossarium-einträge', function () {
    actingAsAdmin();

    $response = postJson('/api/ai/varro/validate', [
        'lemma' => 'discere',
        'bedeutung' => 'lernen',
        'wortart' => 'verb',
    ]);

    expect($response)->toBeSuccessfulApiResponse();
    expect($response->json('data.is_valid'))->toBeTrue();
})->group('integration');

2. Sparsame Verwendung

Da Integration-Tests echte API-Credits verbrauchen:

  • Nicht für jeden Test: Nur kritische Pfade testen
  • Nicht in CI/CD per Default: Gezielt triggern, nicht bei jedem Push
  • Sinnvolle Frequenz: Wöchentlich oder vor Releases ausführen
  • Dokumentation: Erwartete Kosten pro Testlauf dokumentieren

3. Realistische Testdaten

php
test('tiro generiert lateinischen prüfungstext', function () {
    actingAsAdmin();

    $response = postJson('/api/ai/tiro/generate-exam-text', [
        'topic' => 'Caesars Gallienkrieg',
        'difficulty' => 'advanced',
        'word_count' => 150,
        'grammatical_phenomena' => ['ablativus absolutus', 'cum-Sätze'],
    ]);

    expect($response)->toBeSuccessfulApiResponse();

    $text = $response->json('data.text');
    expect($text)->toBeString();
    expect($text)->toContain('Caesar'); // Thematische Validierung
    expect(str_word_count($text))->toBeGreaterThan(140); // Längenprüfung
})->group('integration');

4. Error-Handling testen

php
test('varro gibt sinnvolle fehlermeldung bei ungültiger eingabe', function () {
    actingAsAdmin();

    $response = postJson('/api/ai/varro/validate', [
        'lemma' => '', // Ungültige Eingabe
        'bedeutung' => 'lernen',
        'wortart' => 'verb',
    ]);

    expect($response)->toHaveApiError(422);
    expect($response->json('errors'))->toHaveKey('lemma');
})->group('integration');

5. Timeout-Konfiguration

AI-Services können länger brauchen - angemessene Timeouts setzen:

php
test('tiro generiert langen text ohne timeout', function () {
    // Timeout auf 60 Sekunden setzen
    $this->timeout(60);

    actingAsAdmin();

    $response = postJson('/api/ai/tiro/generate-text', [
        'topic' => 'Römische Geschichte',
        'word_count' => 500, // Längerer Text
    ]);

    expect($response)->toBeSuccessfulApiResponse();
})->group('integration')->timeout(60000); // Millisekunden

Beispiel: Vollständiger Integration-Test

php
<?php

use function Pest\Laravel\{postJson};

/**
 * Integration-Tests für Varro (AI-Glossarium-Validator)
 *
 * Hinweis: Diese Tests verbrauchen echte API-Credits!
 * Nur bei Bedarf ausführen: php artisan test --group=integration
 */

beforeEach(function () {
    actingAsAdmin();
});

test('varro validiert korrekte nomen-einträge', function () {
    $response = postJson('/api/ai/varro/validate', [
        'lemma' => 'puella',
        'bedeutung' => 'Mädchen',
        'wortart' => 'nomen',
        'genus' => 'f',
        'deklinationsklasse' => 'a',
    ]);

    expect($response)->toBeSuccessfulApiResponse();
    expect($response->json('data.is_valid'))->toBeTrue();
    expect($response->json('data.confidence'))->toBeGreaterThan(0.8);
    expect($response->json('data.suggestions'))->toBeArray();
})->group('integration');

test('varro erkennt falsche bedeutungen', function () {
    $response = postJson('/api/ai/varro/validate', [
        'lemma' => 'puella',
        'bedeutung' => 'Junge', // Falsche Bedeutung
        'wortart' => 'nomen',
        'genus' => 'f',
        'deklinationsklasse' => 'a',
    ]);

    expect($response)->toBeSuccessfulApiResponse();
    expect($response->json('data.is_valid'))->toBeFalse();
    expect($response->json('data.issues'))->toContain('bedeutung');
    expect($response->json('data.correct_bedeutung'))->toBe('Mädchen');
})->group('integration');

test('varro validiert korrekte verb-einträge', function () {
    $response = postJson('/api/ai/varro/validate', [
        'lemma' => 'amare',
        'bedeutung' => 'lieben',
        'wortart' => 'verb',
        'konjugationsklasse' => 'a',
    ]);

    expect($response)->toBeSuccessfulApiResponse();
    expect($response->json('data.is_valid'))->toBeTrue();
    expect($response->json('data.confidence'))->toBeGreaterThan(0.9);
})->group('integration');

test('varro gibt sinnvolle vorschläge bei tippfehlern', function () {
    $response = postJson('/api/ai/varro/validate', [
        'lemma' => 'discre', // Tippfehler
        'bedeutung' => 'lernen',
        'wortart' => 'verb',
    ]);

    expect($response)->toBeSuccessfulApiResponse();
    expect($response->json('data.is_valid'))->toBeFalse();
    expect($response->json('data.suggestions'))->toContain('discere');
})->group('integration');

CI/CD-Integration

GitHub Actions Beispiel

yaml
name: Integration Tests

on:
  # Manuell triggerbar
  workflow_dispatch:

  # Wöchentlich am Montag
  schedule:
    - cron: '0 9 * * 1'

  # Vor Releases
  push:
    tags:
      - 'v*'

jobs:
  integration-tests:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'

      - name: Install Dependencies
        run: composer install

      - name: Setup Test Database
        run: php artisan test:setup

      - name: Run Integration Tests
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: php artisan test --testsuite=Integration

Kosten-Monitoring

Testlauf-Kosten schätzen

php
// In tests/Integration/README.md dokumentieren:

# Geschätzte Kosten pro Testlauf

- **Varro Integration-Tests**: ca. 0.05 EUR (5 Tests, je ~1000 Tokens)
- **Tiro Integration-Tests**: ca. 0.15 EUR (3 Tests, je ~5000 Tokens)
- **Grammaticus Integration-Tests**: ca. 0.08 EUR (4 Tests, je ~2000 Tokens)

**Gesamt pro Testlauf**: ca. 0.28 EUR

**Empfohlene Frequenz**: Wöchentlich oder vor Major-Releases

Logging für Cost-Tracking

php
test('varro test mit cost-logging', function () {
    $startTime = microtime(true);

    $response = postJson('/api/ai/varro/validate', [
        'lemma' => 'puella',
        'bedeutung' => 'Mädchen',
        'wortart' => 'nomen',
    ]);

    $duration = microtime(true) - $startTime;

    // Token-Usage aus Response loggen
    $tokensUsed = $response->json('data.meta.tokens_used');
    Log::channel('integration')->info('Varro Test', [
        'test' => 'varro validiert korrekte nomen-einträge',
        'tokens' => $tokensUsed,
        'duration' => $duration,
        'cost_estimate' => $tokensUsed * 0.000003, // EUR pro Token (Beispiel)
    ]);

    expect($response)->toBeSuccessfulApiResponse();
})->group('integration');

Troubleshooting

Problem: "Test-Datenbank nicht gefunden"

bash
# Lösung: Test-Setup ausführen
php artisan test:setup

Problem: "API-Key fehlt"

bash
# Prüfen ob API-Keys in .env.testing gesetzt sind
cat .env.testing | grep ANTHROPIC_API_KEY

Problem: "Timeout-Fehler"

php
// Timeout in Test erhöhen
test('langsamer api call', function () {
    // ...
})->timeout(120000); // 120 Sekunden

Problem: "Rate-Limiting"

php
// Sleep zwischen Tests einfügen
test('test 1', function () {
    // ...
    sleep(2); // 2 Sekunden Pause
})->group('integration');

Weitere Ressourcen