Skip to content

Pest Datasets - Wiederverwendbare Testdaten

Diese Dokumentation beschreibt die verfügbaren Pest Datasets für parametrisierte Tests in Hermeneus.

Übersicht

Datasets befinden sich in tests/Datasets/ und bieten wiederverwendbare Testdaten für verschiedene Domänen:

  • users.php - User-Rollen und Authentifizierung
  • vocab.php - Vokabel- und Morphologie-Daten
  • uebungen.php - Übungs-Module und Konfigurationen

Was sind Datasets?

Datasets ermöglichen parametrisierte Tests, die mit verschiedenen Eingabewerten ausgeführt werden:

php
test('addition funktioniert', function (int $a, int $b, int $expected) {
    expect($a + $b)->toBe($expected);
})->with([
    [1, 2, 3],
    [5, 5, 10],
    [0, 0, 0],
]);

Benannte Datasets können wiederverwendet werden:

php
dataset('numbers', [
    [1, 2, 3],
    [5, 5, 10],
]);

test('addition', fn($a, $b, $expected) => expect($a + $b)->toBe($expected))
    ->with('numbers');

User Datasets (tests/Datasets/users.php)

roles - Alle Rollen

Alle verfügbaren User-Rollen.

Werte:

  • admin
  • editor
  • tester
  • teacher
  • user

Verwendung:

php
test('user kann einloggen', function (string $role) {
    actingAsRole($role);

    $response = getJson('/api/user');
    expect($response->status())->toBe(200);
})->with('roles');

Ausgabe beim Testen:

✓ user kann einloggen (admin)
✓ user kann einloggen (editor)
✓ user kann einloggen (tester)
✓ user kann einloggen (teacher)
✓ user kann einloggen (user)

elevated_roles - Erhöhte Rechte

Rollen mit erhöhten Berechtigungen (Admin, Editor, Tester).

Werte:

  • admin
  • editor
  • tester

Verwendung:

php
test('nur privilegierte user können übung bearbeiten', function (string $role) {
    actingAsRole($role);

    $response = putJson('/api/uebungen/1', ['title' => 'Geändert']);
    expect($response->status())->toBe(200);
})->with('elevated_roles');

test('normale user werden blockiert', function (string $role) {
    actingAsRole($role);

    $response = putJson('/api/uebungen/1', ['title' => 'Geändert']);
    expect($response->status())->toBe(403);
})->with('regular_roles');

regular_roles - Normale Rollen

Rollen ohne erhöhte Berechtigungen (Teacher, User).

Werte:

  • teacher
  • user

Verwendung:

php
test('normale user können eigene texte sehen', function (string $role) {
    actingAsRole($role);

    $response = getJson('/api/my-texts');
    expect($response->status())->toBe(200);
})->with('regular_roles');

base_data_users - Komplette User-Details

Vollständige Informationen zu allen Base-Data Usern.

Struktur:

php
[
    'admin' => [
        'username' => 'bruce.wayne',
        'email' => 'bruce.wayne@gotham-academy.test',
        'role' => 'admin',
    ],
    // ...
]

Verwendung:

php
test('user hat korrekte email', function (array $userData) {
    $user = getBaseDataUser($userData['role']);

    expect($user->username)->toBe($userData['username']);
    expect($user->email)->toBe($userData['email']);
    expect($user->role)->toBe($userData['role']);
})->with('base_data_users');

Vokabel Datasets (tests/Datasets/vocab.php)

wortarten - Alle Wortarten

Alle Wortarten im Hermeneus-Glossarium.

Werte:

  • nomen
  • verb
  • adjektiv
  • pronomen
  • partikel
  • numerale
  • eigenname
  • wendung

Verwendung:

php
test('lemma kann für wortart erstellt werden', function (string $wortart) {
    $lemma = createLemmaForWortart($wortart);

    expect($lemma->wortart)->toBe($wortart);
})->with('wortarten');

morphable_wortarten - Morphologisierbare Wortarten

Nur Wortarten mit Flexionsformen.

Werte:

  • nomen
  • verb
  • adjektiv
  • pronomen
  • numerale

Ausgeschlossen:

  • partikel (keine Flexion)
  • eigenname (keine Flexion)
  • wendung (keine Flexion)

Verwendung:

php
test('lemma kann morphologisiert werden', function (string $wortart) {
    $lemma = createLemmaForWortart($wortart);

    expect($lemma)->toBeMorphable();
})->with('morphable_wortarten');

deklinationsklassen - Deklinationsklassen

Deklinationsklassen für Nomina mit Beispielen.

Struktur:

php
[
    'a' => ['klasse' => 'a', 'beispiel' => 'puella, -ae f.'],
    'o' => ['klasse' => 'o', 'beispiel' => 'dominus, -i m.'],
    'kons' => ['klasse' => 'kons', 'beispiel' => 'rex, regis m.'],
    'e' => ['klasse' => 'e', 'beispiel' => 'res, rei f.'],
    'u' => ['klasse' => 'u', 'beispiel' => 'manus, -us f.'],
    'gem' => ['klasse' => 'gem', 'beispiel' => 'civis, -is m./f.'],
]

Verwendung:

php
test('deklinationsklasse wird korrekt zugeordnet', function (array $dekl) {
    $nomen = createNomen($dekl['klasse']);

    expect($nomen->deklinationsklasse)->toBe($dekl['klasse']);
})->with('deklinationsklassen');

konjugationsklassen - Konjugationsklassen

Konjugationsklassen für Verben mit Beispielen.

Struktur:

php
[
    'a' => ['klasse' => 'a', 'beispiel' => 'amare'],
    'e' => ['klasse' => 'e', 'beispiel' => 'monere'],
    'kons' => ['klasse' => 'kons', 'beispiel' => 'legere'],
    'i' => ['klasse' => 'i', 'beispiel' => 'audire'],
    'gem' => ['klasse' => 'gem', 'beispiel' => 'capere'],
]

Verwendung:

php
test('konjugationsklasse wird erkannt', function (array $konj) {
    $verb = Verb::where('lemma', $konj['beispiel'])->first();

    expect($verb->konjugationsklasse)->toBe($konj['klasse']);
})->with('konjugationsklassen');

genera - Geschlechter

Grammatikalische Genera.

Struktur:

php
[
    'm' => ['genus' => 'm', 'bezeichnung' => 'maskulin'],
    'f' => ['genus' => 'f', 'bezeichnung' => 'feminin'],
    'n' => ['genus' => 'n', 'bezeichnung' => 'neutrum'],
]

Verwendung:

php
test('genus wird korrekt gespeichert', function (array $genusData) {
    $nomen = Nomen::factory()->create([
        'genus' => $genusData['genus']
    ]);

    expect($nomen->genus)->toBe($genusData['genus']);
})->with('genera');

kasus - Fälle

Lateinische Kasus.

Struktur:

php
[
    'nom' => ['kasus' => 'nom', 'bezeichnung' => 'Nominativ'],
    'gen' => ['kasus' => 'gen', 'bezeichnung' => 'Genitiv'],
    'dat' => ['kasus' => 'dat', 'bezeichnung' => 'Dativ'],
    'akk' => ['kasus' => 'akk', 'bezeichnung' => 'Akkusativ'],
    'abl' => ['kasus' => 'abl', 'bezeichnung' => 'Ablativ'],
    'vok' => ['kasus' => 'vok', 'bezeichnung' => 'Vokativ'],
]

Verwendung:

php
test('kasus werden in morphostring kodiert', function (array $kasusData) {
    $morphoString = createMorphoStringWithKasus($kasusData['kasus']);

    expect($morphoString)->toContain($kasusData['kasus']);
})->with('kasus');

numeri - Singular/Plural

Numerus-Kategorien.

Struktur:

php
[
    'sg' => ['numerus' => 'sg', 'bezeichnung' => 'Singular'],
    'pl' => ['numerus' => 'pl', 'bezeichnung' => 'Plural'],
]

Verwendung:

php
test('numerus wird erkannt', function (array $numerusData) {
    $form = createFormWithNumerus($numerusData['numerus']);

    expect($form->numerus)->toBe($numerusData['numerus']);
})->with('numeri');

Übungs Datasets (tests/Datasets/uebungen.php)

uebung_aliases - Alle Übungsmodule

Alle registrierten Übungsmodule aus der UebungenRegistry.

Dynamisch geladen: Wird zur Laufzeit aus der Registry generiert.

Beispielwerte:

  • uebung-bedeutungen-zuordnen
  • uebung-formen-bestimmen
  • uebung-vokabelnlernen
  • ...

Verwendung:

php
test('übung kann erstellt werden', function (string $alias) {
    actingAsAdmin();

    $response = postJson("/api/uebungen/{$alias}/store", [
        'title' => 'Test Übung',
        'content_data' => getDefaultContentData($alias),
    ]);

    expect($response)->toBeSuccessfulApiResponse();
})->with('uebung_aliases');

Wichtig: Alle verfügbaren Module werden getestet!

absolvable_uebungen - Absolvierbare Übungen

Nur Übungen mit absolvable: true in config.json.

Dynamisch gefiltert: Basiert auf Registry-Konfiguration.

Verwendung:

php
test('übung kann absolviert werden', function (string $alias) {
    actingAsUser();

    $uebung = createUebung($alias);

    $response = postJson("/api/uebungen/{$uebung->id}/absolve");
    expect($response)->toBeSuccessfulApiResponse();
})->with('absolvable_uebungen');

evaluable_uebungen - Evaluierbare Übungen

Nur Übungen mit evaluable: true in config.json.

Dynamisch gefiltert: Basiert auf Registry-Konfiguration.

Verwendung:

php
test('übung kann ausgewertet werden', function (string $alias) {
    actingAsUser();

    $uebung = createUebung($alias);
    $submission = createSubmission($uebung);

    $response = postJson("/api/uebungen/{$uebung->id}/evaluate", [
        'submission' => $submission,
    ]);

    expect($response)->toBeSuccessfulApiResponse();
    expect($response->json())->toHaveKey('evaluation');
})->with('evaluable_uebungen');

timetrackable_uebungen - Zeiterfassbare Übungen

Nur Übungen mit timetrackable: true in config.json.

Dynamisch gefiltert: Basiert auf Registry-Konfiguration.

Verwendung:

php
test('zeiterfassung funktioniert', function (string $alias) {
    actingAsUser();

    $uebung = createUebung($alias);

    $response = postJson("/api/uebungen/{$uebung->id}/track-time", [
        'duration' => 120, // Sekunden
    ]);

    expect($response)->toBeSuccessfulApiResponse();
})->with('timetrackable_uebungen');

uebung_crud_examples - CRUD-Beispieldaten

Konkrete Beispieldaten für verschiedene Übungstypen (nicht dynamisch).

Struktur:

php
[
    'uebung-bedeutungen-zuordnen' => [
        'alias' => 'uebung-bedeutungen-zuordnen',
        'type' => 'vocab-based',
    ],
    'uebung-formen-bestimmen' => [
        'alias' => 'uebung-formen-bestimmen',
        'type' => 'morphology-based',
    ],
    'uebung-vokabelnlernen' => [
        'alias' => 'uebung-vokabelnlernen',
        'type' => 'vocab-based',
    ],
]

Verwendung:

php
test('crud operations für übungstyp', function (array $example) {
    actingAsEditor();

    $alias = $example['alias'];
    $type = $example['type'];

    // Create
    $response = postJson("/api/uebungen/{$alias}/store", [
        'title' => "Test {$alias}",
    ]);
    expect($response)->toBeSuccessfulApiResponse();

    $id = $response->json('data.id');

    // Read
    $response = getJson("/api/uebungen/{$id}");
    expect($response)->toBeSuccessfulApiResponse();

    // Update
    $response = putJson("/api/uebungen/{$id}", [
        'title' => "Updated {$alias}",
    ]);
    expect($response)->toBeSuccessfulApiResponse();

    // Delete
    $response = deleteJson("/api/uebungen/{$id}");
    expect($response)->toBeSuccessfulApiResponse();
})->with('uebung_crud_examples');

Best Practices

1. Spezifische Datasets bevorzugen

php
// SCHLECHT: Zu breit
test('test', function (string $role) {
    // ...
})->with('roles'); // Testet auch irrelevante Rollen

// GUT: Präzise
test('test', function (string $role) {
    // ...
})->with('elevated_roles'); // Nur relevante Rollen

2. Datasets kombinieren

php
test('user kann übung für wortart erstellen', function (string $role, string $wortart) {
    actingAsRole($role);

    $lemma = createLemmaForWortart($wortart);
    // Test-Code
})
    ->with('elevated_roles')
    ->with('morphable_wortarten');

Erzeugt: Kombinatorische Tests (elevated_roles × morphable_wortarten)

3. Eigene Datasets definieren

php
// In Test-Datei
dataset('test_uebungen', [
    'uebung-bedeutungen-zuordnen',
    'uebung-formen-bestimmen',
]);

test('test', fn($alias) => /* ... */)->with('test_uebungen');

4. Named Datasets für Lesbarkeit

php
// Ohne Namen (unklar)
->with([
    ['admin', true],
    ['user', false],
]);

// Mit Namen (klar)
->with([
    'admin can access' => ['admin', true],
    'user is blocked' => ['user', false],
]);

Ausgabe:

✓ test (admin can access)
✗ test (user is blocked)

Erweiterte Nutzung

Lazy Datasets

Für aufwendige Berechnungen:

php
dataset('expensive_data', function () {
    return expensive_computation();
});

Shared Datasets

Datasets können über mehrere Test-Dateien geteilt werden (bereits implementiert in tests/Datasets/).

Closure-basierte Datasets

php
dataset('dynamic_users', function () {
    yield fn() => getBaseDataUser('admin');
    yield fn() => getBaseDataUser('editor');
});

Troubleshooting

"Dataset not found"

Stelle sicher, dass die Dataset-Datei in tests/Datasets/ existiert und korrekt benannt ist.

"Empty dataset"

Dynamische Datasets (uebung_aliases, etc.) benötigen eine funktionierende Applikation mit geladener Registry.

"Too many test cases"

Bei kombinatorischen Tests mit with()->with():

php
// Erzeugt: 5 roles × 5 wortarten = 25 Tests
->with('roles')
->with('wortarten')

// Reduziere auf relevante Kombinationen:
->with('elevated_roles')  // 3 roles
->with('morphable_wortarten')  // 5 wortarten = 15 Tests

Weitere Ressourcen