Coverage Highlighting direkt im Editor statt nur im HTML-Report
AI generated
IDE
{ }
PhpStorm · PHPUnit · Coverage
Coverage Highlighting direkt im Editor
statt nur im HTML-Report blaettern

Ein HTML-Coverage-Report ist gut fuer den Ueberblick, aber schlecht zum Arbeiten. PhpStorm zeigt Testabdeckung direkt farbig im Editor-Gutter an, sodass ungedeckte Zeilen sofort dort sichtbar sind, wo gerade programmiert wird.

14 Min. Lesezeit Code Coverage PHPUnit Editor-Gutter

1. Warum ein HTML-Report allein den Workflow bremst

Ein klassischer HTML-Coverage-Report, generiert per PHPUnit und geoeffnet im Browser, liefert eine gute Gesamtuebersicht ueber Prozentzahlen pro Klasse und Datei. Fuer die konkrete Arbeit am Code bedeutet er aber einen staendigen Kontextwechsel: Report oeffnen, Datei suchen, Zeile identifizieren, zurueck zum Editor wechseln, die passende Stelle wiederfinden. Bei jeder neuen Testrunde beginnt dieser Zyklus von vorne, was bei iterativer Testentwicklung schnell mehr Zeit kostet als das eigentliche Schreiben der Tests.

PhpStorm loest dieses Problem, indem es Coverage-Daten direkt in den Editor projiziert, und zwar an genau der Stelle, an der ohnehin gerade gearbeitet wird. Statt zwischen Browser und IDE hin und her zu wechseln, bleibt der Blick durchgehend im Code, waehrend farbige Markierungen im Gutter, also dem schmalen Streifen links neben den Zeilennummern, sofort zeigen, welche Zeilen von der letzten Testrunde erreicht wurden und welche nicht.

2. Einen Coverage-Lauf aus PhpStorm heraus starten

Ein PHPUnit-Testlauf mit Coverage-Erfassung wird nicht ueber den normalen Run-Button gestartet, sondern ueber den danebenliegenden Coverage-Button, erkennbar am Schild-Symbol, oder ueber das Kontextmenue mit der Option Run with Coverage. Dabei nutzt PhpStorm im Hintergrund entweder Xdebug oder PCOV als Coverage-Treiber, abhaengig davon, welche Extension im PHP-Interpreter des Projekts aktiviert und in den PHP-Einstellungen als Coverage-Engine hinterlegt ist.

Bei Docker-basierten Magento-Setups, wie sie mit Mark Shusts docker-magento ueblich sind, muss der verwendete PHP-Interpreter in PhpStorm auf den Container-Interpreter zeigen, damit Xdebug oder PCOV tatsaechlich im richtigen Kontext greifen. Ein haeufiger Stolperstein ist, dass Xdebug im Container zwar fuer Debugging aktiviert ist, aber der coverage-Modus in der xdebug.mode-Einstellung fehlt, was PhpStorm zwar den Testlauf ausfuehren, aber keine Coverage-Daten liefern laesst.


# In php.ini bzw. docker/php.ini des Magento-Containers:
# xdebug.mode muss "coverage" enthalten, sonst bleibt der Editor-Gutter leer
xdebug.mode=develop,debug,coverage

# Alternative mit PCOV, deutlich schneller fuer reine Coverage-Laeufe:
# pcov.enabled=1
# pcov.directory=/var/www/html/app/code

# nach einer Aenderung in php.ini den PHP-FPM-Prozess neu starten:
bin/restart

3. Die Coverage-Farben im Gutter richtig lesen

Nach einem Coverage-Lauf faerbt PhpStorm jede Zeile im Editor-Gutter in eine von drei Farben: Gruen fuer Zeilen, die mindestens einmal ausgefuehrt wurden, Rot fuer Zeilen, die im Testlauf keinmal erreicht wurden, und ein neutrales Grau oder Ungefaerbtes fuer Zeilen, die von PHPUnit gar nicht als ausfuehrbarer Code gezaehlt werden, etwa reine Kommentare oder Leerzeilen. Diese Dreiteilung macht auf den ersten Blick sichtbar, wo in einer Klasse noch Testluecken bestehen, ohne eine einzige Prozentzahl lesen zu muessen.

Besonders aufschlussreich ist die Kombination mit bedingten Verzweigungen: Eine if-Anweisung kann teilweise gruen erscheinen, wenn nur ein Zweig durchlaufen wurde, waehrend der else-Block rot bleibt. Diese Zeilen-genaue Granularitaet ist der eigentliche Mehrwert gegenueber dem HTML-Report, der zwar auch farbige Zeilen zeigt, aber eben nur nach einem Kontextwechsel weg vom aktuell bearbeiteten Code.

4. Live sehen, was der aktuelle Testfall wirklich abdeckt

Beim Schreiben eines neuen Testfalls lohnt es sich, den Coverage-Lauf gezielt nur fuer die betroffene Testklasse zu starten statt fuer die gesamte Suite. Das reduziert die Laufzeit erheblich und macht sofort sichtbar, ob der gerade geschriebene Test tatsaechlich den beabsichtigten Codepfad erreicht. Ein Test, der erwartungsgemaess gruen faerben sollte, aber rot bleibt, ist ein zuverlaessiges Signal dafuer, dass entweder eine Assertion fehlt oder der Testfall eine ganz andere Codezeile trifft als angenommen.

Dieser enge Feedback-Zyklus veraendert den Testworkflow spuerbar: Statt Tests zu schreiben und erst im Nachhinein per separatem Report zu pruefen, ob sie greifen, laesst sich direkt nach jedem Testlauf im selben Editor-Fenster sehen, welche Zeilen jetzt neu gruen geworden sind. Bei komplexeren Methoden mit mehreren Verzweigungen ist das der Unterschied zwischen geraten und tatsaechlich verifiziertem Testverhalten.

5. Workflow: Gezielt ungedeckte Bereiche schliessen

Ein effizienter Ansatz fuer bestehenden Code mit niedriger Abdeckung ist, zunaechst einen Coverage-Lauf ueber die relevante Klasse oder das relevante Modul zu starten und dann gezielt von oben nach unten durch die rot markierten Zeilen zu gehen. Fuer jeden roten Block wird ein minimaler, gezielter Testfall geschrieben, der genau diesen Pfad ausloest, gefolgt von einem erneuten, schnellen Coverage-Lauf, um zu bestaetigen, dass die Zeile jetzt gruen ist.

Dieses iterative Vorgehen eignet sich besonders gut fuer Legacy-Code in gewachsenen Magento-Modulen, bei dem eine vollstaendige Testabdeckung auf einen Schlag unrealistisch ist. Statt sich an einer abstrakten Prozentzahl zu orientieren, die sich erst nach dem kompletten Testlauf aktualisiert, arbeitet man sich Zeile fuer Zeile durch den tatsaechlich riskanten, ungetesteten Code, was den groessten Sicherheitsgewinn pro investierter Testminute liefert.


// Beispiel: nach dem Coverage-Lauf ist der else-Zweig rot markiert
public function calculateDiscount(float $price, ?CustomerGroup $group): float
{
    if ($group !== null && $group->isWholesale()) {
        return $price * 0.85; // gruen: durch bestehenden Test abgedeckt
    }

    return $price; // rot: bisher kein Test mit $group === null
}

// Gezielter Testfall, der genau die rote Zeile ausloest:
public function testCalculateDiscountReturnsFullPriceWithoutGroup(): void
{
    $result = $this->calculator->calculateDiscount(100.0, null);
    $this->assertSame(100.0, $result);
}

6. Xdebug- und PCOV-Coverage-Modi im Vergleich

Xdebug liefert sehr detaillierte Coverage-Daten inklusive Branch- und Path-Coverage, ist dafuer aber spuerbar langsamer, da es jede einzelne Codezeile waehrend der Ausfuehrung instrumentiert. Bei grossen Testsuiten in Magento-Projekten mit vielen hundert Testfaellen kann dieser Overhead die Laufzeit eines vollstaendigen Coverage-Laufs von Minuten auf ein Vielfaches verlaengern, was den Live-Feedback-Charakter des Editor-Gutters untergraebt, wenn jeder Lauf zu lange dauert.

PCOV ist speziell fuer Coverage-Erfassung entwickelt und deutlich schneller als Xdebug im Coverage-Modus, liefert dafuer aber keine Branch-Coverage, sondern nur Line-Coverage, was fuer die im Editor-Gutter angezeigte Zeilenfaerbung in der Praxis vollkommen ausreicht. Fuer den taeglichen Live-Workflow im Editor ist PCOV daher meist die bessere Wahl, waehrend ein vollstaendiger Xdebug-Coverage-Lauf mit Branch-Details eher fuer gelegentliche, detaillierte Analysen reserviert bleibt.

7. Gesamte Suite versus einzelne Testklasse: Die richtige Wahl treffen

Ein Coverage-Lauf ueber die gesamte Testsuite liefert das vollstaendigste Bild, eignet sich aber wegen der Laufzeit selten fuer den unmittelbaren Editier-Zyklus. Sinnvoller ist es, waehrend der aktiven Entwicklung an einer Klasse gezielt nur die zugehoerige Testklasse oder eine thematisch passende Test-Suite mit Coverage auszufuehren, und den vollstaendigen Suite-Lauf erst vor einem Commit oder als Teil der CI-Pipeline durchzufuehren.

PhpStorm erlaubt es, Run-Konfigurationen fuer genau diesen Zweck zu speichern, etwa eine Konfiguration, die nur die Tests eines bestimmten Verzeichnisses mit Coverage ausfuehrt. Diese Konfigurationen lassen sich per Tastenkuerzel erneut ausloesen, sodass der Coverage-Lauf ueber die relevante Teilmenge nach jeder Codeaenderung mit minimalem Aufwand wiederholt werden kann, ohne jedes Mal Pfade neu auszuwaehlen.

8. Coverage-Gutter und teamweite Schwellwerte kombinieren

Das Editor-Gutter ersetzt keine automatisierten Coverage-Schwellwerte in der CI-Pipeline, ergaenzt sie aber sinnvoll. Waehrend ein CI-Job global durchsetzt, dass die Gesamtabdeckung eines Moduls einen bestimmten Prozentsatz nicht unterschreitet, hilft das lokale Gutter dabei, waehrend der eigentlichen Entwicklungsarbeit genau zu erkennen, welche neuen Zeilen den Schwellwert gefaehrden, bevor der Push ueberhaupt stattfindet.

In der Praxis bewaehrt sich die Kombination aus einem strengen CI-Schwellwert fuer neu hinzugefuegten Code und einer lockereren Vorgabe fuer bestehenden Legacy-Code, waehrend das lokale Gutter in PhpStorm waehrend der Entwicklung als schnelles, visuelles Frühwarnsystem dient. So wird eine rote Zeile im Editor oft schon behoben, lange bevor der CI-Job ueberhaupt einen Verstoss meldet.

9. Praxis-Tipps fuer den taeglichen Umgang mit dem Coverage-Gutter

Das Coverage-Gutter bleibt nach einem Lauf bestehen, bis es manuell ueber Generate Coverage Report oder einen erneuten Lauf aktualisiert wird, was gelegentlich zu veralteten Anzeigen fuehrt, wenn zwischenzeitlich Code geaendert wurde, ohne die Tests neu auszufuehren. Ein kurzer Blick auf den Zeitstempel des letzten Coverage-Laufs in der Coverage-Toolbar hilft, solche veralteten Anzeigen zu erkennen, bevor eine falsche Schlussfolgerung ueber den tatsaechlichen Testzustand gezogen wird.

Fuer Multi-Modul-Magento-Projekte lohnt es sich, den Coverage-Scope in den Run-Konfigurationen bewusst auf das gerade bearbeitete Modul einzuschraenken, statt versehentlich das gesamte app/code-Verzeichnis zu instrumentieren. Das haelt die Laufzeit niedrig und verhindert, dass irrelevante Coverage-Daten aus fremden Modulen die eigene Analyse verwaessern oder den Editor-Gutter in Dateien einfaerben, die mit der aktuellen Aufgabe gar nichts zu tun haben.

Coverage-Engine Geschwindigkeit Branch-Coverage Empfohlener Einsatz
Xdebug Langsamer Ja, detailliert Gelegentliche Tiefenanalyse einzelner Klassen
PCOV Deutlich schneller Nein, nur Line-Coverage Taeglicher Live-Workflow im Editor-Gutter
Kein Treiber aktiv Kein Coverage-Lauf moeglich Nicht verfuegbar In php.ini xdebug.mode oder pcov.enabled setzen
Gesamte Suite mit Coverage Laenger, vollstaendiges Bild Abhaengig von Engine Vor Commit oder in der CI-Pipeline
Einzelne Testklasse mit Coverage Sehr schnell Abhaengig von Engine Waehrend aktiver Entwicklung an einer Klasse

Mironsoft

PhpStorm-Setup, Docker-Integration und Team-Produktivität

PhpStorm, das für Magento- und PHP-Projekte wirklich optimal läuft?

Wir prüfen bestehende PhpStorm-Setups auf langsame Indizierung, ungenutzte Docker-Integration und fehlende Team-Konventionen und richten eine Konfiguration ein, die von der ersten Sekunde an produktiv ist.

Setup-Review

Indexing, Interpreter und Speicher-Einstellungen für große Magento-Projekte optimieren.

Docker-Integration

Xdebug, PHPUnit und Datenbank-Tools sauber mit dem Docker-Setup verbinden.

Team-Konventionen

Inspection-Profile, Code-Style und Live-Templates projektweit vereinheitlichen.

10. Zusammenfassung

Coverage Highlighting im Editor: Das Wichtigste auf einen Blick

Farbcode im Gutter

Gruen fuer ausgefuehrte, Rot fuer nicht erreichte, Grau fuer nicht ausfuehrbare Zeilen.

PCOV fuer den Alltag

Deutlich schneller als Xdebug im Coverage-Modus, ideal fuer den engen Live-Feedback-Zyklus.

Gezielt Luecken schliessen

Rote Zeilen von oben nach unten mit minimalen, gezielten Testfaellen schrittweise gruen faerben.

Ergaenzt CI-Schwellwerte

Das lokale Gutter warnt schon waehrend der Entwicklung, bevor die CI-Pipeline einen Verstoss meldet.

11. FAQ: Coverage Highlighting im Editor: Das Wichtigste auf einen Blick

1Wie starte ich einen PHPUnit-Testlauf mit Coverage in PhpStorm?
Ueber den Coverage-Button neben dem normalen Run-Button, erkennbar am Schild-Symbol, oder ueber Run with Coverage im Kontextmenue. PhpStorm nutzt dabei Xdebug oder PCOV als Coverage-Treiber.
2Warum bleibt der Editor-Gutter nach einem Testlauf leer?
Meist fehlt in der php.ini der Wert coverage im xdebug.mode, oder es ist weder Xdebug noch PCOV im verwendeten PHP-Interpreter aktiviert. Nach einer Aenderung in der php.ini muss PHP-FPM neu gestartet werden.
3Was bedeuten die Farben Gruen, Rot und Grau im Coverage-Gutter?
Gruen zeigt Zeilen, die mindestens einmal ausgefuehrt wurden. Rot zeigt Zeilen, die im Testlauf nie erreicht wurden. Grau beziehungsweise ungefaerbt markiert Zeilen, die PHPUnit gar nicht als ausfuehrbaren Code zaehlt, etwa Kommentare.
4Was ist der Unterschied zwischen Xdebug- und PCOV-Coverage?
Xdebug liefert detaillierte Branch-Coverage, ist dabei aber deutlich langsamer. PCOV liefert nur Line-Coverage, ist dafuer aber erheblich schneller und eignet sich besser fuer den taeglichen Live-Workflow im Editor.
5Sollte ich Coverage immer ueber die gesamte Testsuite laufen lassen?
Fuer die aktive Entwicklung nicht, da die Laufzeit den engen Feedback-Zyklus stoert. Besser ist ein Coverage-Lauf nur ueber die aktuell bearbeitete Testklasse, waehrend der vollstaendige Suite-Lauf vor einem Commit oder in der CI-Pipeline erfolgt.
6Wie erkenne ich, ob das Coverage-Gutter veraltete Daten anzeigt?
Ein Blick auf den Zeitstempel des letzten Coverage-Laufs in der Coverage-Toolbar zeigt, ob seitdem Code geaendert wurde, ohne die Tests erneut auszufuehren. In dem Fall sollte der Coverage-Lauf einfach wiederholt werden.
7Ersetzt das Editor-Gutter Coverage-Schwellwerte in der CI-Pipeline?
Nein, beide ergaenzen sich. Die CI-Pipeline erzwingt global einen Mindestwert, waehrend das lokale Gutter waehrend der Entwicklung sofort visuell zeigt, welche neuen Zeilen noch ungetestet sind.
8Wie gehe ich systematisch gegen niedrige Testabdeckung in Legacy-Code vor?
Von oben nach unten durch die rot markierten Zeilen gehen, fuer jeden roten Block einen minimalen gezielten Testfall schreiben und mit einem erneuten Coverage-Lauf bestaetigen, dass die Zeile jetzt gruen ist.
9Wie verhindere ich, dass fremde Module den Coverage-Gutter verfaelschen?
Den Coverage-Scope in der Run-Konfiguration bewusst auf das gerade bearbeitete Modul einschraenken, statt das gesamte app/code-Verzeichnis zu instrumentieren.
10Funktioniert Coverage Highlighting auch bei Docker-basierten Magento-Setups?
Ja, solange der in PhpStorm konfigurierte PHP-Interpreter auf den Container zeigt und dort Xdebug mit aktiviertem coverage-Modus oder PCOV verfuegbar ist. Nach Aenderungen an der php.ini muss der Container-PHP-Prozess neu gestartet werden.