Zurück zur Startseite

PHPUnit covers: Navigation und Testabdeckung für Entwickler

Der Artikel erklärt, wie man covers-Annotationen und -Attribute in PHPUnit verwendet, um die Navigation zwischen Tests und Anwendungs-Code zu verbessern. Er behandelt Ansätze zum Verknüpfen von Tests mit Methoden, IDE-Einrichtung und Abdeckungsbeschränkungen.

Verbesserung des Testens in PHP: Leitfaden zu covers in PHPUnit
Advertisement 728x90

PHPUnit: @covers meistern für bessere Test-Navigation und Abdeckung

Beim Testen von Web-Controllern in PHP entstehen oft Navigationsprobleme zwischen Tests und App-Code. Wir schauen uns an, wie die @covers-Annotationen und -Attribute von PHPUnit das lösen und die Entwicklung vereinfachen – ohne Abdeckung zu opfern.

Das Navigationsproblem zwischen Tests und Code

Beim Testen von Controllern über HTTP-Requests können Sie Methoden nicht direkt aufrufen, was den Sprung vom Test zum Code erschwert. Ein Test für den /hello-Endpoint referenziert z. B. GreetingController::hello() nicht direkt. Das zwingt zu manuellen IDE-Suchen und bremst Sie aus.

Hier ein Beispiel-Controller und Test:

Google AdInline article slot
final class GreetingController extends AbstractController
{  
    #[Route('/hello')]
    public function hello(): Response
    {
        return new Response($this->generate("Hello!"));
    }
}
class GreetingControllerTest extends WebTestCase
{
    public function test_hello(): void
    {
        $content = get('/hello');
        assert_starts_with('Hello!', $content);
    }
}

Drei Wege, Tests mit Code zu verknüpfen

Entwickler nutzen verschiedene Tricks, um die Navigation zu verbessern.

1. Native Syntax mit Reflection

Ersetzen Sie String-Pfade durch Methodenaufrufe via Reflection, z. B. request(GreetingController::hello(...)). Nachteil: Tests verlieren Unabhängigkeit vom App-Code und brechen bei Änderungen.

Google AdInline article slot

2. @see-Annotation

PHPDoc zum Verlinken nutzen:

/**
 * @see \App\Controller\GreetingController::hello()
 */
public function test_hello(): void { ... }

Vorteile: IDE-Unterstützung. Nachteile: Volle Klassenpfade nötig, generisches Tag ohne Spezialbehandlung.

Google AdInline article slot

3. PHPUnit-spezifische Covers

Annotationen oder Attribute, speziell für Abdeckung und Navigation gebaut.

Covers-Annotationen in PHPUnit nutzen

Vor PHPUnit 12 herrschten @coversDefaultClass und @covers:

/**
 * @coversDefaultClass \App\Controller\GreetingController
 */
class GreetingControllerTest extends WebTestCase
{
    /**
     * @covers ::hello
     */
    public function test_hello(): void { ... }
}

Vorteile:

  • Exzellente PhpStorm-Unterstützung: Autovervollständigung, Navigation, Nutzungsanalyse.
  • Eigene Vorlagen für Test-Generierung.

PhpStorm-Vorlagen-Nachteile:

  • Begrenzt auf zwei PHPUnit-Vorlagen.
  • Verwirrende Namen.
  • Gelegentliche Generator-Fehler.

Umstieg auf Covers-Attribute in PHPUnit 12+

PHPUnit 12 hat Annotationen durch Attribute ersetzt, aber nur für Klassen, nicht Methoden.

Grundnutzung:

#[CoversClass('App\Controller\GreetingController')]
class GreetingControllerTest extends WebTestCase
{
    public function test_hello(): void { ... }
}

Das mindert die Navigationspräzision ohne Methodenspezifika.

Methoden mit CoversMethod spezifizieren:

#[CoversMethod('App\Controller\GreetingController', 'hello')]
#[CoversMethod('App\Controller\GreetingController', 'bye')]
class GreetingControllerTest extends WebTestCase
{
    public function test_hello(): void { ... }
    public function test_bye(): void { ... }
}

Nachteil: Attribut-Wirrwarr bei Multi-Methoden-Tests.

Beste Strategie: Eine Methode, eine Testklasse

Dedizierte Testklassen pro Methode vereinfachen:

#[CoversMethod('App\Controller\GreetingController', 'hello')]
class HelloTest extends WebTestCase
{
    public function test_hello(): void { ... }
    public function test_hello2(): void { ... }
}

Vorteile:

  • Weniger Kopfarbeit.
  • Keine pro-Methode-Covers nötig.
  • Fördert sauberes Design: Ein Controller, ein Endpoint.

Attribut-Vorlagen funktionieren wie Annotationen, brauchen aber manuelle CoversMethod-Anpassungen nach Generierung.

IDE-Integration und zukünftige Verbesserungen

PhpStorm beherrscht schon Sprünge Test-zu-Klasse via Strg+Shift+T. Methoden-Level-Navigation folgt bald.

Wichtige Erkenntnisse

  • Covers für Navigationsboost nutzen, aber Abdeckungseinfluss beachten.
  • PHPUnit-12+-Attribute sind klassenbasiert – passen Sie Tests an.
  • Ideal: Eine Testklasse pro Methode für einfache Wartung.
  • IDE-Vorlagen für Auto-Covers einrichten.
  • PhpStorm-Updates für bessere Attribut-Unterstützung abwarten.

Abdeckungsgrenzen: Covers' größte Schwäche

Covers' Kernaufgabe ist das Scopen der Abdeckung auf Klassen/Methoden. CoversClass schließt externen Code aus Reports aus – super für strenge Projekte, aber die meisten wollen nur Lücken finden.

Workarounds zum Deaktivieren:

  • Overkill-Hack: Skripte, die Tags vor Testlauf entfernen.
  • Praktische Lösung: phpunit/php-code-coverage via Composer patchen.

Je nach Projekt und Team wählen.

— Editorial Team

Advertisement 728x90

Weiterlesen