Aktualisiere die Datenbank einmal vor Beginn der Prüfung

Laravel PHPUnit - Tests automatisch als Pre-Commit-Hook ausführen

profile
Von Stefan Dreßler
3. Februar 2020
Aktualisiere die Datenbank einmal vor Beginn der Prüfung

Dieser Artikel zeigt, wie du eine neue Datenbank einmal migrierst, bevor du mit dem Testen beginnst, und wie du Tests automatisch vor jedem Git-Commit in einer separaten Testdatenbank ausführst. Basierend auf Laravel 5.7.

"Die besten Tests sind die, die häufig, schnell und automatisch laufen. Sie sollten in einer sauberen und separaten Testdatenbank laufen und uns davor bewahren, ungetesteten Code in unser Git-Repository zu committen."

Laravel verfügt über den Trait "RefreshDatabase". Dieser Trait wird erstellt, um die Datenbank vor jedem Test zu aktualisieren. Bei großen Datenbanken verlangsamt dies das Testen erheblich. In unserem Fall wollen wir eine frische Datenbank , bevor wir mit den Tests beginnen. Also erstellen wir einen Trait, der php artisan migrate:fresh --seed einmal ausführt, bevor der Test beginnt.

Die folgenden Komponenten sollten bereits vorhanden sein:

  1. Laravel Framework (der Artikel basiert auf v5.7)

  2. PHPUnit wird ausgeführt (Artikel basiert auf v7.3.5)

  3. Du hast Laravels Migrationen, Factories und Seeds aufgebaut.

  4. Deine Tests erweitern die Datei TestCase.php aus dem Verzeichnis tests.

Du solltest grünes Licht bekommen, wenn du die folgenden Befehle ausführst

php artisan migrate:fresh --seed phpunit

Entferne "RefreshDatabase"

Laravel wird mit dieser Eigenschaft ausgeliefert, aber sie wird so erstellt, dass die Datenbank vor jedem Test aktualisiert wird. Wenn du also mit diesem Trait herumgespielt hast, solltest du ihn aus deiner allgemeinen TestCase.php entfernen.

Lass uns "MigrateFreshSeedOnce" erstellen

Erstelle einen Trait namens "MigrateFreshSeedOnce.php" in deinem Testordner.

Code für den Trait:

Du kannst die Artisan-Befehle einfach nach Belieben bearbeiten.

<?php namespace Tests; use Illuminate\Support\Facades\Artisan; trait MigrateFreshSeedOnce { /** * Bei true ist das Setup mindestens einmal gelaufen. * @var boolean */ protected static $setUpHasRunOnce = false; /** * Nach dem ersten Lauf von setUp "migrate:fresh --seed" * @return void */ public function setUp() { parent::setUp(); if (!static::$setUpHasRunOnce) { Artisan::call('migrate:fresh'); Artisan::call( 'db:seed', ['--class' => 'DatabaseSeeder'] ); static::$setUpHasRunOnce = true; } }

Verwende diesen neuen Trait in deiner tests/TestCase.php

... abstract class TestCase extends BaseTestCase { use CreatesApplication, MigrateFreshSeedOnce; ...

Das war's!

Wenn du phpunit ausführst, wird php artisan migrate:fresh --seed einmal ausgeführt, bevor deine Tests beginnen. In unserem Fall laufen die Funktionstests mit dieser Eigenschaft 98 % schneller. Probiere phpunit --testdox für gut lesbare Ergebnisse.

Separate Testdatenbank verwenden

Funktionstests sollten immer in einer separaten Testdatenbank laufen. Erstelle also deine Testdatenbank und stelle sicher, dass dein bestehender Datenbankbenutzer alle Rechte für diese neue Datenbank hat. Suche dann deine phpunit.xml und bearbeite den "php"-Block am Ende.

Übertrage nie wieder ungetesteten Code. Automatisiere!

Um die Tests häufig durchzuführen und unser Repository von ungetestetem Code sauber zu halten, haben wir uns entschieden, PHPUnit automatisch über einen Pre-Commit-Hook auszuführen. Wenn ein Test fehlschlägt, wird der Git-Commit zwei Mal fehlschlagen. Jetzt ist es also bewiesen: "Committed Code ist getesteter Code."

Erstelle einfach eine Datei namens "pre-commit" in deinem lokalen git hooks-Verzeichnis und füge diesen Code hinzu. vim .git/hooks/pre-commit

#!/usr/bin/env php <?php echo "Running tests.. "; exec('vendor/bin/phpunit', $output, $returnCode); if ($returnCode !== 0) { // Vollständige Ausgabe anzeigen echo PHP_EOL . implode($output, PHP_EOL) . PHP_EOL; echo "Abbruch der Übertragung..." . PHP_EOL; exit(1); } // Zusammenfassung anzeigen (letzte Zeile) echo array_pop($output) . PHP_EOL; exit(0);

Nach allem

Wenn deine Tests immer noch zu viel Zeit für einen Pre-Commit-Hook verbrauchen, versuche sie zu vereinfachen oder Teile davon auszuführen. Vielleicht lassen Sie nur Ihre UnitTests laufen:

exec('vendor/bin/phpuni tests/Unit', $output, $returnCode)

Das war's!

Ich hoffe, du hattest Spaß beim Lesen dieses Artikels. Bitte lass mich wissen, wenn du Fragen oder Anregungen hast.