IDE
{ }
PhpStorm · PHPUnit · Docker · Magento Tests · Coverage
PhpStorm mit PHPUnit in Docker und Magento-Projekten
sauber nutzen

PHPUnit in PhpStorm zu nutzen ist trivial, wenn PHP lokal installiert ist. Mit Docker-Interpretern, Magento-spezifischen Bootstrap-Dateien und Integration-Tests, die eine laufende Datenbank brauchen, wird die Konfiguration komplexer. Dieser Guide zeigt, wie man jeden dieser Fälle sauber löst.

16 Min. Lesezeit PHPUnit · Docker · Magento · Coverage · Run-Konfigurationen PhpStorm 2024+ · PHPUnit 11 · PHP 8.4

1. Die Herausforderung: PHPUnit in komplexen Umgebungen

PHPUnit in PhpStorm mit einem lokalen PHP-Interpreter zu nutzen ist unkompliziert: Test-Framework auswählen, auf PHPUnit zeigen, Run-Konfiguration anlegen, fertig. Sobald aber PHP im Docker-Container läuft, verändert sich alles. PhpStorm muss PHP-Befehle im Container ausführen, Path-Mappings zwischen lokalem Dateisystem und Container-Pfaden auflösen und Test-Output korrekt in das IDE-Fenster streamen. Noch komplexer wird es bei Magento 2: Unit-Tests benötigen einen spezifischen Bootstrap, Integration-Tests benötigen eine laufende Datenbank und vorkonfigurierte Magento-Installation im Container.

Die häufigsten Fehler ohne saubere Konfiguration: PhpStorm findet PHPUnit nicht im Container, Test-Output erscheint nicht im IDE-Panel, Coverage-Reports werden nicht generiert, und Breakpoints in Tests werden nicht getroffen, weil Xdebug im Test-Kontext nicht aktiv ist. Jeder dieser Fehler hat eine konkrete Lösung, die nichts mit dem Test-Code selbst zu tun hat, sondern ausschließlich mit der IDE-Konfiguration. Wer diese Konfiguration einmal sauber eingerichtet hat, profitiert dauerhaft von einer Test-Umgebung, die sich nahtlos in den Entwicklungsworkflow einfügt.

2. Remote-Interpreter für PHPUnit in Docker einrichten

Unter Settings → PHP → CLI Interpreter legt man einen Docker-Interpreter an: From Docker, Vagrant, VM, WSL... auswählen, den phpfpm-Service aus der compose.yaml auswählen. PhpStorm verbindet sich mit Docker und liest die PHP-Konfiguration aus dem Container. Dieser Interpreter wird dann unter Settings → PHP → Test Frameworks → PHPUnit als Basis-Interpreter für PHPUnit-Ausführungen gewählt. Wichtig: PHPUnit muss im Container verfügbar sein – entweder als Composer-Abhängigkeit (vendor/bin/phpunit) oder als direkt installiertes Binary.

Für den Path-zu-PHPUnit unter PHPUnit Local (trotz des Namens, der verwirrt – es ist der Pfad im Container-Kontext) trägt man /var/www/html/vendor/bin/phpunit ein, also den Pfad wie er im Container existiert. PhpStorm übersetzt diesen automatisch via Path-Mappings auf die lokale Datei. Die Alternative PHPUnit by Remote Interpreter ist die explizitere Option, bei der man direkt den Docker-Interpreter und den Container-Pfad zu PHPUnit angibt. Bei neu eingerichteten Projekten ist diese Option klarer, weil sie die Verbindung zwischen Interpreter und PHPUnit-Binary explizit macht.


<?php
// phpunit.xml.dist — PHPUnit configuration for Mironsoft Magento 2 project
// Located at: src/dev/tests/unit/phpunit.xml.dist

// <?xml version="1.0" encoding="UTF-8"?>
// <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
//          xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.0/phpunit.xsd"
//          bootstrap="framework/autoload.php"
//          colors="true"
//          beStrictAboutOutputDuringTests="true"
//          stopOnError="false"
//          stopOnFailure="false">
//   <testsuites>
//     <testsuite name="Mironsoft_Unit">
//       <directory>../../../app/code/Mironsoft/*/Test/Unit</directory>
//     </testsuite>
//   </testsuites>
//   <coverage>
//     <include>
//       <directory suffix=".php">../../../app/code/Mironsoft</directory>
//     </include>
//     <exclude>
//       <directory>../../../app/code/Mironsoft/*/Test</directory>
//     </exclude>
//   </coverage>
// </phpunit>

// In PhpStorm: Run → Edit Configurations → PHPUnit
// Test runner: defined in configuration file
// Configuration file: /var/www/html/dev/tests/unit/phpunit.xml.dist (container path)

3. PHPUnit-Run-Konfigurationen in PhpStorm anlegen

Run-Konfigurationen in PhpStorm sind gespeicherte Einstellungen für einen bestimmten Test-Run. Für ein Magento-Projekt empfiehlt es sich, mindestens drei Run-Konfigurationen anzulegen: Eine für alle Unit-Tests des Projekts (mit phpunit.xml.dist), eine für alle Unit-Tests eines spezifischen Moduls (filtert auf einen Ordner), und eine für Integration-Tests (mit einer anderen phpunit.xml). Diese Konfigurationen lassen sich unter Run → Edit Configurations → PHPUnit anlegen und unter .idea/runConfigurations/ als XML-Dateien speichern – und damit ins Repository committen.

Wichtige Einstellungen in jeder Run-Konfiguration: Den korrekten Docker-Interpreter auswählen, den Pfad zur phpunit.xml als Container-Pfad angeben und unter Environment Variables alle Umgebungsvariablen eintragen, die der Test-Bootstrap benötigt. Für Magento bedeutet das oft TESTS_CLEANUP=disabled für schnellere Integration-Test-Runs oder MFTF_UTILS=0 um MFTF-spezifische Initialisierungen zu überspringen. Die Run-Konfigurationen erscheinen dann in der Toolbar und lassen sich mit einem Klick oder über den Shortcut Shift+F10 starten.

4. Unit-Tests: schnell, isoliert, ohne Datenbankzugriff

Unit-Tests in Magento 2 befinden sich per Konvention unter app/code/Vendor/Module/Test/Unit/ und nutzen keine Datenbankverbindung, keinen Magento-Service-Container und keine echten DI-Instanzen. Stattdessen werden alle Abhängigkeiten als Mocks übergeben. PHPUnit 11 in Kombination mit PHP 8.4 und Strict Types erlaubt besonders präzise Test-Code-Organisation: Return-Type-Declarations auf Mock-Methoden, Intersection-Types für gemockte Interfaces und Constructor Promotion in Test-Klassen selbst.

In PhpStorm läuft ein einzelner Unit-Test mit einem Klick auf das grüne Play-Icon in der Gutter neben der Test-Methode oder der Testklasse. PhpStorm öffnet automatisch das Test-Ergebnis-Panel und zeigt Pass/Fail-Status, Assertion-Details bei Fehlern und die Laufzeit jedes Tests. Über Run → Run Tests in Parallel lassen sich bei größeren Test-Suiten mehrere Tests gleichzeitig ausführen – PhpStorm verwaltet dabei die parallelen Container-Starts automatisch. Das Ergebnis-Panel erlaubt außerdem, fehlgeschlagene Tests direkt zu filtern und nur diese erneut auszuführen.


<?php
declare(strict_types=1);

namespace Mironsoft\Catalog\Test\Unit\Model;

use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Api\Data\ProductInterface;
use Mironsoft\Catalog\Model\ProductService;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

/**
 * Unit test for ProductService — no database, no real DI container.
 * Runs in PhpStorm via Gutter-Icon or Run Configuration.
 */
class ProductServiceTest extends TestCase
{
    private ProductService $productService;
    private ProductRepositoryInterface&MockObject $repositoryMock;

    protected function setUp(): void
    {
        // Create mock using intersection type (PHP 8.1+)
        $this->repositoryMock = $this->createMock(ProductRepositoryInterface::class);

        $this->productService = new ProductService(
            productRepository: $this->repositoryMock,
        );
    }

    /**
     * @test
     */
    public function getBySku_returnsProduct_whenFound(): void
    {
        $productMock = $this->createMock(ProductInterface::class);
        $productMock->method('getSku')->willReturn('test-sku');

        $this->repositoryMock
            ->expects(self::once())
            ->method('get')
            ->with('test-sku')
            ->willReturn($productMock);

        $result = $this->productService->getBySku('test-sku');

        self::assertSame($productMock, $result);
    }
}

5. Integration-Tests in Magento: Bootstrap und Datenbanksetup

Magentos Integration-Tests befinden sich unter dev/tests/integration/ und benötigen eine vollständige Magento-Installation mit Datenbankzugriff. Der Bootstrap (dev/tests/integration/framework/bootstrap.php) startet Magento ohne Webserver, initialisiert die Datenbank aus einer separaten Test-Datenbank und stellt den vollständigen DI-Container bereit. Die Konfiguration der Test-Datenbankverbindung erfolgt über dev/tests/integration/etc/install-config-mysql.php.

In PhpStorm konfiguriert man für Integration-Tests eine eigene Run-Konfiguration, die auf dev/tests/integration/phpunit.xml.dist zeigt und den Docker-Interpreter nutzt. Der wichtigste Unterschied zur Unit-Test-Konfiguration: Die Test-Datenbankverbindung muss im Container erreichbar sein. Bei Mark-Shust-Setup bedeutet das, den MariaDB-Service-Namen als Datenbankhost zu verwenden (db oder mysql), nicht localhost. Integration-Tests dauern wesentlich länger als Unit-Tests – PhpStorm zeigt im Test-Panel den Fortschritt und stoppt bei konfigurierten Abbruchbedingungen wie stopOnFailure.

6. Code-Coverage in PhpStorm anzeigen und auswerten

Code-Coverage zeigt, welche Codezeilen durch Tests abgedeckt werden – grün für abgedeckt, rot für nicht abgedeckt. In PhpStorm aktiviert man Coverage über den Coverage-Button (das Schild-Icon) neben dem Run-Button oder über Run → Run with Coverage. PhpStorm startet dann PHPUnit mit Xdebug oder PCOV als Coverage-Driver und zeigt das Ergebnis direkt im Editor als farbige Randleiste an. Gleichzeitig öffnet sich das Coverage-Panel mit Prozentangaben pro Klasse und Methode.

Wichtig für die Coverage-Konfiguration: Xdebug muss im Coverage-Modus laufen (XDEBUG_MODE=coverage) oder PCOV muss als schnellere Alternative installiert sein. PCOV ist für reine Coverage-Messungen deutlich schneller als Xdebug, kann aber nicht gleichzeitig für Debugging verwendet werden. In der phpunit.xml gibt man an, welche Verzeichnisse in die Coverage-Messung einbezogen und welche ausgeschlossen werden. Für Magento bedeutet das: eigene Module einschließen, Magento-Core und Composer-Pakete ausschließen.

7. Tests filtern, neu starten und debuggen

PhpStorm erlaubt es, Tests auf verschiedene Arten zu filtern und erneut auszuführen. Im Test-Ergebnis-Panel gibt es Buttons, um nur fehlgeschlagene Tests, nur laufende Tests oder nur ignorierte Tests anzuzeigen. Ein Rechtsklick auf eine Test-Suite oder einen einzelnen Test im Panel öffnet ein Kontextmenü mit Rerun-Optionen. Außerdem kann man direkt im Editor-Code auf das Gutter-Icon rechtsklicken und den Test mit einer spezifischen Run-Konfiguration starten.

Für das Debuggen von Tests ist die Integration mit Xdebug in PhpStorm besonders wertvoll. Statt Run verwendet man Debug (der Käfer-Button), und PhpStorm startet PHPUnit mit aktiviertem Xdebug. Breakpoints in Test-Methoden und im zu testenden Code werden korrekt getroffen, der Debugger zeigt den kompletten Call-Stack und alle Variablen an. Das ist besonders hilfreich bei komplexen Unit-Tests mit vielen Mock-Interaktionen, wo man verstehen möchte, welche Mock-Methoden in welcher Reihenfolge aufgerufen werden.

8. Test-Fixtures und Data-Provider für saubere Tests

Data Provider in PHPUnit 11 sind Methoden oder statische Methoden (empfohlen in PHPUnit 11), die Testdaten als Iterator oder Array zurückgeben. PhpStorm unterstützt Data Provider vollständig: Im Test-Ergebnis-Panel erscheint jeder Datensatz als eigener Eintrag mit dem Data-Provider-Key als Label. Fehlschläge zeigen exakt an, welcher Datensatz das Problem verursacht hat. Das macht Data-Provider-Tests deutlich einfacher zu debuggen als Loops in Test-Methoden.

Für Magento Integration-Tests gibt es das Fixture-System mit den Annotationen @magentoDataFixture und @magentoAppIsolation. Diese Annotationen laden PHP-Dateien, die Testdaten in die Datenbank eintragen, und stellen sicher, dass nach jedem Test die Datenbank in einen definierten Zustand zurückversetzt wird. PhpStorm kann diese Annotationen nicht direkt auflösen – es handelt sich um Magento-spezifische PHPUnit-Extensions – aber Code-Navigation zu den Fixture-Dateien funktioniert über Ctrl+Click auf den Dateinamen im Annotationswert.


<?php
declare(strict_types=1);

namespace Mironsoft\Pricing\Test\Unit\Model;

use Mironsoft\Pricing\Model\PriceCalculator;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

/**
 * Tests PriceCalculator with data providers — each dataset visible separately in PhpStorm.
 */
class PriceCalculatorTest extends TestCase
{
    private PriceCalculator $calculator;

    protected function setUp(): void
    {
        $this->calculator = new PriceCalculator();
    }

    /**
     * Static data provider — recommended in PHPUnit 11.
     *
     * @return array<string, array{float, float, float}>
     */
    public static function priceProvider(): array
    {
        return [
            'standard price'     => [100.0, 0.19, 119.0],
            'reduced rate'       => [200.0, 0.07, 214.0],
            'zero tax'           => [50.0,  0.0,  50.0],
            'fractional result'  => [33.33, 0.19, 39.66],
        ];
    }

    #[DataProvider('priceProvider')]
    public function testGrossPriceCalculation(
        float $net,
        float $taxRate,
        float $expectedGross,
    ): void {
        // Each dataset appears as separate entry in PhpStorm test panel
        self::assertEqualsWithDelta(
            $expectedGross,
            $this->calculator->calculateGross($net, $taxRate),
            0.01,
        );
    }
}

9. Test-Typen in Magento 2 im Vergleich

Magento 2 unterscheidet mehrere Test-Ebenen mit unterschiedlichen Anforderungen an Laufzeit, Infrastruktur und PhpStorm-Konfiguration. Die Wahl des richtigen Test-Typs hat direkte Auswirkungen darauf, wie schnell Feedback aus PhpStorm kommt.

Test-Typ Laufzeit Infrastruktur PhpStorm-Setup
Unit-Tests Millisekunden Nur PHP im Container Einfach, phpunit.xml.dist
Integration-Tests Sekunden bis Minuten PHP + Datenbank + Magento Eigene Run-Konfiguration
API-Functional-Tests Sekunden bis Minuten Vollständige Magento-Instanz Separate Konfiguration
MFTF (Functional) Minuten bis Stunden Browser + Selenium + Magento Extern, nur CLI
Performance-Tests Stunden JMeter + Magento Nicht in PhpStorm

Für die tägliche Entwicklungsarbeit mit PhpStorm sind Unit-Tests und Integration-Tests die relevanten Ebenen. Unit-Tests lassen sich mit dem Gutter-Icon direkt aus dem Editor starten und liefern in Millisekunden Feedback. Integration-Tests werden sinnvollerweise über eine Run-Konfiguration für das gesamte Modul gestartet und vor Pull-Request-Erstellung ausgeführt. MFTF und Performance-Tests gehören in die CI-Pipeline und werden nicht interaktiv in PhpStorm ausgeführt.

Mironsoft

Magento 2 Testing, PHPUnit-Setup und Testautomatisierung

PHPUnit in Magento und Docker produktiv einsetzen?

Wir richten PHPUnit für euer Magento-Projekt ein: Docker-Interpreter, Run-Konfigurationen für Unit- und Integration-Tests, Coverage-Reporting und Pre-Commit-Hooks – damit Tests kein Aufwand, sondern Standard sind.

Test-Setup

PHPUnit mit Docker-Interpreter und Magento-Bootstrap korrekt konfigurieren

Coverage-Reporting

PCOV oder Xdebug für Coverage einrichten, HTML-Reports und PhpStorm-Integration

Test-Strategie

Unit- vs. Integration-Tests sinnvoll aufteilen und in CI-Pipeline integrieren

10. Zusammenfassung

PHPUnit in PhpStorm mit Docker und Magento sauber zu nutzen erfordert einmalige Konfigurationsarbeit in vier Bereichen: den Docker-Interpreter korrekt einrichten, Run-Konfigurationen für verschiedene Test-Typen anlegen, Coverage-Reporting aktivieren und die Magento-spezifischen Bootstrap-Anforderungen berücksichtigen. Einmal konfiguriert, lassen sich Tests mit einem Klick oder Shortcut starten, Ergebnisse erscheinen direkt im IDE-Panel, und Coverage wird als farbige Overlay-Darstellung im Editor angezeigt.

Der größte Effekt liegt in der Beschleunigung des Test-Feedback-Loops. Statt Tests in einem separaten Terminal mit CLI-Befehlen zu starten und Output zu scrollen, startet man den Test direkt aus dem Editor, sieht das Ergebnis sofort im IDE-Panel und kann bei Fehlern mit einem Klick zur fehlschlagenden Assertion navigieren. Das macht Testing zu einem natürlichen Teil des Entwicklungsworkflows statt zu einem separaten Schritt, den man nach dem Schreiben von Code durchführt.

PHPUnit in PhpStorm — Das Wichtigste auf einen Blick

Docker-Interpreter

Settings → PHP → CLI Interpreter → From Docker. PHPUnit-Pfad im Container: /var/www/html/vendor/bin/phpunit. Path-Mappings korrekt setzen.

Run-Konfigurationen

Separate Konfigurationen für Unit- und Integration-Tests. Als XML unter .idea/runConfigurations/ ins Repository committen.

Coverage

PCOV für schnelle Coverage, Xdebug für Coverage + Debugging. XDEBUG_MODE=coverage setzen. Coverage erscheint als farbiges Overlay im Editor.

Magento-Integration-Tests

install-config-mysql.php mit Docker-Datenbankhost konfigurieren. Service-Name als Host, nicht localhost. Eigene Run-Konfiguration mit korrektem Bootstrap.

11. FAQ: PhpStorm mit PHPUnit in Docker und Magento

1Wie verbinde ich PHPUnit in PhpStorm mit Docker?
Settings → PHP → CLI Interpreter → From Docker: phpfpm auswählen. Dann Test Frameworks → PHPUnit: Interpreter wählen, Container-Pfad zu vendor/bin/phpunit angeben.
2Warum findet PhpStorm PHPUnit nicht?
Pfad muss Container-Pfad sein: /var/www/html/vendor/bin/phpunit. PHPUnit muss als Composer-Abhängigkeit im Container installiert sein.
3Wie aktiviere ich Code-Coverage?
Run → Run with Coverage (Shield-Button). Xdebug mit XDEBUG_MODE=coverage oder PCOV im Container installieren. Coverage erscheint als grün/rote Randleiste im Editor.
4Magento Integration-Tests in PhpStorm einrichten?
Eigene Run-Konfiguration auf dev/tests/integration/phpunit.xml.dist zeigen. install-config-mysql.php mit Docker-DB-Host konfigurieren. Service-Name als Host, nicht localhost.
5Run-Konfigurationen ins Repository committen?
Ja. .idea/runConfigurations/ als XML-Dateien – für Team-Commits geeignet. Alle Entwickler haben dieselben Konfigurationen ohne erneutes Setup.
6Coverage schlägt fehl – was tun?
XDEBUG_MODE=coverage in Environment Variables setzen. Im Container prüfen: php -m | grep xdebug. PCOV als schnellere Alternative installieren.
7Einzelnen Test direkt aus dem Editor starten?
Grünes Play-Icon in der Gutter neben der Test-Methode klicken. Rechtsklick für Run/Debug. Shortcut: Ctrl+Shift+F10.
8PCOV vs. Xdebug für Coverage?
PCOV ist bis zu 5x schneller, aber kein Debugging. Xdebug: Coverage + Debugging. Für CI-Coverage PCOV, für Debugging-Sessions Xdebug verwenden.
9Data-Provider-Tests in PhpStorm nutzen?
#[DataProvider]-Attribut verwenden (PHPUnit 11). PhpStorm zeigt jeden Datensatz separat im Test-Panel. Fehlschlagende Datensätze direkt identifizierbar.
10Fehlschlagenden Test debuggen?
Debug-Button (Käfer) statt Run. Breakpoints setzen. PhpStorm stoppt, zeigt Call-Stack und Variablen. Xdebug im Container muss aktiv sein.