PHPUNIT Funktionen in einem Laravel Package mit PHPPEST nutzen

Ich integriere PHPPEST in mein Laravel Package, indem ich folgenden Header-Code in die jeweilige Testdatei einfüge:

use Tests\TestCase;
uses(TestCase::class)->in(__DIR__);

Ohne diese Zeilen würden Funktionen wie

$this->get('url');

nicht funktionieren. Mit dieser Integration kann ich PHPUNIT Funktionen in PHPPEST effizient in meinen Laravel Tests verwenden.




Eine zusätzliche Optimierungsmöglichkeit besteht darin, eigene TestCase-Dateien zu erstellen, indem man Tests\TestCase erweitert und um eigene Methoden ergänzt.

Beispiel:

namespace DeinPaketNamespace\Core\App\Classes;

use Tests\TestCase as LaravelTestCase;

class TestCase extends LaravelTestCase
{

    protected function assertClassExist(string $classNameWithNamespace)
    {
        $this->assertTrue(class_exists($classNameWithNamespace));
    }
}

//Am Ende des Files binded man dann die neuen Methoden in Pest ein.
uses(TestCase::class)->in(__DIR__);

in deinem Testfile brauchst du nun nur noch dein eigenes TestCase-File einbinden:

use DeinPaketNamespace\Core\App\Classes\TestCase;
uses(TestCase::class)->in(__DIR__);

Tipps:

  • Nutze die Erweiterung von TestCase, um maßgeschneiderte Testmethoden zu erstellen.

  • Verwende klare und präzise Bezeichnungen für deine Testfunktionen, um ihre Funktionalität transparent zu machen.

  • Strukturiere deine eigenen TestCase-Dateien für eine verbesserte Lesbarkeit und Wartbarkeit des Codes.

Test Driven Development (TDD) nach Robert C. Martin

Test Driven Development (TDD) ist eine Softwareentwicklungsmethode, bei der der Entwicklungsprozess auf das Schreiben von Tests vor der Implementierung des eigentlichen Codes ausgerichtet ist. Es folgt einem einfachen Zyklus, der aus drei Hauptphasen besteht. In diesem Blog-Artikel möchte ich die drei Stages des Test Driven Development (TDD) nach Robert C. Martin, auch bekannt als Uncle Bob, näher erläutern: die rote Kappe, die grüne Kappe und die blaue Kappe.
(Die Analogie der farbigen Kappen hilft Entwicklern, den TDD-Prozess besser zu verstehen und die verschiedenen Phasen zu visualisieren. Es betont die Idee, dass TDD ein iterativer Prozess ist, bei dem Tests und Codeentwicklung eng miteinander verflochten sind, um hochwertige Software zu erstellen. So beschreibt Robert C. Martin den Prozess des TDD. )

  • Rote Kappe (Red Phase): In dieser Phase wird zuerst ein Testfall geschrieben, der die erwartete Funktionalität des zu entwickelnden Codes beschreibt. Der Test wird absichtlich so geschrieben, dass er fehlschlägt, da der Code noch nicht implementiert wurde.
  • Grüne Kappe (Green Phase): Hier wird der eigentliche Code entwickelt, um den Testfall zum Bestehen zu bringen. Das Hauptziel besteht darin, nur den minimalen Code zu schreiben, um den Test erfolgreich zu machen, ohne zusätzliche Funktionalität hinzuzufügen.
  • Blaue Kappe (Blue Phase): In dieser Phase erfolgt das Refactoring des Codes, um sicherzustellen, dass er sauber, wartbar und effizient ist. Es wird kein neuer Funktionscode hinzugefügt, sondern der vorhandene Code wird verbessert.

Dieser Zyklus wird immer wieder wiederholt: Test schreiben, Test bestehen lassen und Code refaktorisieren. Durch diese iterative Vorgehensweise wird sichergestellt, dass der Code immer gut getestet ist und Änderungen oder Erweiterungen am Code keine unerwünschten Nebenwirkungen haben.

TDD hilft Entwicklern, qualitativ hochwertigen Code zu schreiben, da es die Testabdeckung sicherstellt und frühzeitig Probleme erkennt. Es fördert auch das Design von Software, da Entwickler die Anforderungen in kleine, testbare Teile aufteilen müssen. TDD ist ein wichtiger Bestandteil von agilen Entwicklungsmethoden und hat sich als effektive Methode zur Verbesserung der Codequalität und der Entwicklungsproduktivität erwiesen.

1. "Rote Kappe": Test schreiben

Die erste Phase, die "rote Kappe", ist der Ausgangspunkt. Hier schreibe ich den Test, bevor ich irgendeinen Code schreibe. Dieser Test sollte fehlschlagen, da der zugehörige Code noch nicht existiert. Das Beispiel in PHP sieht so aus:

public function testAddition()
{
    $calculator = new Calculator();
    $result = $calculator->add(2, 3);
    $this->assertEquals(5, $result);
}

2. "Grüne Kappe": Code schreiben

Nachdem der Test in der roten Kappe fehlgeschlagen ist, schreibe ich den minimalen Code, um den Test zum Bestehen zu bringen. Dabei ist das Ziel, den Test in der "grünen Kappe" erfolgreich durchzuführen:

class Calculator
{
    public function add($a, $b)
    {
        return $a + $b;
    }
}

3. "Blaue Kappe": Refactoring

In der letzten Phase, der "blauen Kappe", nehme ich mir Zeit, um den Code zu optimieren und zu verbessern, ohne die Funktionalität zu ändern. Refactoring ist entscheidend, um sauberen und wartbaren Code zu erhalten:

class Calculator
{
    public function add(int $a, int $b): int
    {
        return $a + $b;
    }
}

Tipps für effektives TDD:

  • Starte immer mit einem klaren Ziel für deinen Test.
  • Schreibe den einfachsten Testfall zuerst.
  • Erweitere den Code nur, um den aktuellen Testfall zu bestehen.
  • Refactoring sollte regelmäßig erfolgen, um die Codequalität zu erhöhen.
  • Verwende ein Tool wie PHPUnit, um deine Tests automatisch auszuführen.

Laravel Testing: Versteh den Unterschied zwischen Feature und Unit Tests

Als ich bei einer Firma erstmals mit dem richtigen Testen von Applikationen konfrontiert wurde, lernte ich es leider falsch- bzw. verstand Anfangs nicht ganz den Unterschied, wann man was verwenden sollte... Warum? Ich habe leider anfangs die Testlogik von den Unternehmen übernommen - leider hat das Unternehmen das aber Falsch gemacht und hatte unmengen Featuretests im Unittestordner.. Weil ich neu dort war und mit testen noch nicht so viel anfangen konnte- habe ich es falsch übernommen. Leider, damit dir das nicht auch passiert, gibts hier einen kleinen Guide.

In der Welt des Laravel-Entwicklungsprozesses und generell im Developmentbereich ist es entscheidend, Tests zu schreiben, um sicherzustellen, dass unsere Anwendungen stabil und fehlerfrei funktionieren. Es gibt jedoch zwei Haupttypen von Tests, die du kennen solltest: Feature Tests und Unit Tests. Lass uns einen genaueren Blick darauf werfen.

  • Feature Tests: Diese Tests überprüfen die Funktionalität deiner Anwendung auf höherer Ebene. Sie simulieren die Interaktion eines Benutzers mit der Anwendung und testen, ob die Features korrekt funktionieren. Hier ist ein einfaches Beispiel eines Feature Tests in Laravel:
public function test_user_can_login()
{
    $user = User::factory()->create();

    $response = $this->post('/login', [
        'email' => $user->email,
        'password' => 'password',
    ]);

    $response->assertRedirect('/dashboard');
    $this->assertAuthenticatedAs($user);
}
  • Unit Tests: Im Gegensatz dazu überprüfen Unit Tests einzelne Komponenten deiner Anwendung auf ihre korrekte Funktionsweise. Hier ein Beispiel für einen Unit Test in Laravel:
public function test_user_has_full_name()
{
    $user = new User();
    $user->first_name = 'John';
    $user->last_name = 'Doe';

    $this->assertEquals('John Doe', $user->full_name());
}

Es ist wichtig, sowohl Feature Tests als auch Unit Tests in deiner Laravel-Anwendung zu verwenden, um eine umfassende Testabdeckung sicherzustellen und Fehler frühzeitig zu erkennen. Denke daran, dass Feature Tests die Benutzerinteraktion nachbilden, während Unit Tests auf die kleineren Einheiten deines Codes fokussieren.

Laravel: Factories in einem Package nutzen

In diesem Blogbeitrag möchte ich über die Verwendung von Laravel Factories sprechen, einem nützlichen Werkzeug in der Laravel-Welt. Mit Laravel Factories können wir Daten für unsere Tests effizient erstellen, ohne sie manuell eingeben zu müssen. Das spart Zeit und sorgt für konsistente Testdaten. Ich zeige dir, wie du Laravel Factories in deinen Projekten in einem Package nutzen kannst. In unserem Beispiel ist das Package ein unterpackage von Laravia und nennt sich Content. (Im Namespace ersichtlich)

In Laravel sollten Factories in der Regel im Verzeichnis database/factories innerhalb deines Laravel-Projekts erstellt werden. Die Namenskonvention für Factory-Dateien ist, den Namen des Modells in Kleinbuchstaben zu verwenden, gefolgt von "Factory.php". Zum Beispiel, wenn du eine Factory für ein Modell namens "Content" erstellst, sollte die Factory-Datei "ContentFactory.php" heißen.

  • Teile den Composer mit was du vorhast
"autoload": {
        "psr-4": {
            "Laravia\\Content\\Database\\Factories\\": "./src/database/factories"
        }
    },
"autoload-dev": {
        "psr-4": {
            "Laravia\\Content\\Database\\Factories\\": "./src/database/factories",
        }
    },
  • Erstelle eine factory: database/factories/ContentFactory.php
namespace Laravia\Content\Database\Factories;

use Laravia\Content\App\Models\Content;
use Illuminate\Database\Eloquent\Factories\Factory;

class ContentFactory extends Factory
{
    //Sagt deinem Package model zu welcher Klasse die Factory gehört
    protected $model = Content::class;

    //Erstelle die Definition
    public function definition()
    {
        return [
            'body' => $this->faker->text(),
        ];
    }
}
  • Aktiviere die Factory in deinem Package Model: app/Models/Content.php

namespace Laravia\Content\App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Laravia\Content\Database\Factories\ContentFactory;

class Content extends Model
{
    use HasFactory;

    protected static function newFactory()
    {
        return ContentFactory::new();
    }
}
  • du kannst nun in tests oder wo auch immer du die factory verwenden willst so einbinden:
Content::factory()->create(['body' => 'linux']);

Hier gehts zur Laravel Doku