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:
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.
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.
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
Noch keine Kommentare.