aus PHPStorm für Magento starten
Magento 2 bringt eine eigene Testinfrastruktur mit, die sich erheblich von einem Standard-PHPUnit-Projekt unterscheidet. Wer Integrationstests direkt aus PHPStorm starten, Coverage-Berichte in der IDE sehen und einzelne Testmethoden mit einem Klick debuggen will, braucht spezifische Konfigurationen – die dieser Artikel vollständig abdeckt.
Inhaltsverzeichnis
- 1. Magento-Testinfrastruktur verstehen
- 2. Voraussetzungen: Testdatenbank und Umgebungsvariablen
- 3. phpunit.xml für Unit- und Integrationstests konfigurieren
- 4. Run-Konfigurationen in PHPStorm anlegen
- 5. Code-Coverage mit Xdebug aktivieren und auswerten
- 6. Einzelne Tests und Methoden direkt aus dem Editor starten
- 7. Eine vollständige Magento-Integrationstest-Klasse schreiben
- 8. Unit- vs. Integrationstests im Vergleich
- 9. Typische Fehler und ihre Ursachen
- 10. Zusammenfassung
- 11. FAQ
1. Magento-Testinfrastruktur verstehen
Magento 2 unterscheidet drei Testarten, die sich in Aufwand, Laufzeit und Infrastrukturanforderungen grundlegend unterscheiden. Unit-Tests testen einzelne Klassen isoliert, ohne Datenbankzugriff und ohne Magento-Bootstrap – sie laufen in Sekunden. Integrationstests benötigen eine vollständig installierte Magento-Instanz mit dedizierter Testdatenbank und können Minuten dauern. Functional-Tests (MFTF) benötigen einen laufenden Browser und einen Webserver – sie gehören in CI-Pipelines, nicht in den IDE-Workflow.
Der Magento-Testrahmen basiert auf PHPUnit, erweitert ihn aber durch eigene Basis-Klassen. Integrationstests erben von Magento\TestFramework\TestCase\AbstractController oder Magento\TestFramework\TestCase\AbstractIntegrationTestCase, nicht von PHPUnit\Framework\TestCase. Diese Basisklassen bootstrappen Magento vor jedem Test, rollback die Datenbank danach zurück und stellen den ObjectManager zur Verfügung. PHPStorm kann all das direkt starten – aber die Run-Konfiguration muss auf die richtige phpunit.xml und den richtigen Working Directory zeigen.
2. Voraussetzungen: Testdatenbank und Umgebungsvariablen
Integrationstests benötigen eine separate Datenbank – sie darf nicht die Produktions- oder Entwicklungsdatenbank sein, da die Tests nach jedem Test-Lauf Daten manipulieren und über Transaktions-Rollbacks bereinigen. Der Datenbankname ist per Konvention magento_integration_tests. In der Datei dev/tests/integration/etc/install-config-mysql.php wird die Datenbankverbindung für Integrationstests konfiguriert. Diese Datei wird nicht in Git versioniert – jeder Entwickler pflegt seine eigene lokale Version.
Im Docker-Setup muss die Testdatenbank im MySQL-Container erstellt werden: docker exec db mysql -uroot -p -e "CREATE DATABASE magento_integration_tests CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;". Anschließend muss die install-config-mysql.php mit den Container-internen Datenbankzugangsdaten befüllt werden. Innerhalb des PHP-Containers ist der MySQL-Host der Service-Name db, nicht localhost. Das ist ein häufiger Fehler: die Host-Adresse aus der normalen .env übernommen, aber im Container gilt eine andere Auflösung als auf dem Host.
<?php
// dev/tests/integration/etc/install-config-mysql.php
// DO NOT COMMIT – contains local database credentials
return [
'db-host' => 'db', // Docker service name, not localhost
'db-user' => 'magento',
'db-password' => 'magento',
'db-name' => 'magento_integration_tests',
'db-prefix' => '',
'backend-frontname' => 'backend',
'admin-user' => \Magento\TestFramework\Bootstrap::ADMIN_NAME,
'admin-password' => \Magento\TestFramework\Bootstrap::ADMIN_PASSWORD,
'admin-email' => 'admin@example.com',
'admin-firstname' => 'Admin',
'admin-lastname' => 'Test',
'amqp-host' => '',
'amqp-port' => '',
'elasticsearch-host' => 'opensearch',
'elasticsearch-port' => '9200',
];
3. phpunit.xml für Unit- und Integrationstests konfigurieren
Magento liefert für Integrationstests eine phpunit.xml.dist unter dev/tests/integration/. Diese Datei sollte kopiert und als phpunit.xml angepasst werden – die Kopie wird ebenfalls nicht versioniert. In der phpunit.xml werden Testsuite-Pfade, Coverage-Filter und Umgebungsvariablen konfiguriert. Der entscheidende Unterschied zur Standard-PHPUnit-Konfiguration: das bootstrap-Attribut zeigt auf dev/tests/integration/framework/bootstrap.php, das den gesamten Magento-Bootstrap-Prozess startet.
Für Unit-Tests gibt es eine separate phpunit.xml.dist unter dev/tests/unit/. Unit-Tests laufen ohne Datenbankzugriff und ohne Bootstrap – sie sind erheblich schneller und eignen sich für schnelle Feedback-Zyklen während der Entwicklung. PHPStorm kann beide Testsuiten als separate Run-Konfigurationen haben: eine für schnelle Unit-Tests beim Speichern, eine für Integrationstests vor dem Commit. Der Filter im Coverage-Report wird über <include>-Pfade in der phpunit.xml gesteuert – nur die eigenen Module sollten dabei gemessen werden, nicht der Magento-Core.
4. Run-Konfigurationen in PHPStorm anlegen
Run-Konfigurationen für PHPUnit werden in PHPStorm unter Run → Edit Configurations → + → PHPUnit angelegt. Für Integrationstests: Test-Scope auf Defined in the configuration file setzen, als Konfigurationsdatei dev/tests/integration/phpunit.xml eintragen, den Remote-Interpreter (Docker Compose phpfpm) auswählen und das Working Directory auf das Magento-Root im Container setzen: /var/www/html. Die Umgebungsvariablen aus der Compose-Datei werden automatisch vererbt.
Für Unit-Tests legt man eine zweite Konfiguration mit dev/tests/unit/phpunit.xml an. Hier kann auch Test-Scope → Directory mit dem Pfad zum eigenen Modul gewählt werden, um nur die Tests des aktuell entwickelten Moduls auszuführen. PHPStorm zeigt alle Run-Konfigurationen in der Toolbar und ermöglicht schnelles Umschalten. Keyboard-Shortcut Ctrl+Shift+F10 startet den Test der aktuell geöffneten Klasse direkt – ohne Run-Konfiguration auswählen zu müssen.
<?php
// dev/tests/integration/phpunit.xml — relevant configuration sections
/*
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="..."
colors="true"
columns="80"
bootstrap="./framework/bootstrap.php"
stderr="true">
<testsuites>
<!-- Custom module tests only — faster than full suite -->
<testsuite name="Mironsoft_Module Integration Tests">
<directory>../../../app/code/Mironsoft/*/Test/Integration</directory>
</testsuite>
</testsuites>
<coverage>
<include>
<directory suffix=".php">../../../app/code/Mironsoft</directory>
</include>
<exclude>
<directory>../../../app/code/Mironsoft/*/Test</directory>
</exclude>
</coverage>
<php>
<ini name="memory_limit" value="-1" />
<ini name="date.timezone" value="Europe/Berlin" />
</php>
</phpunit>
*/
5. Code-Coverage mit Xdebug aktivieren und auswerten
Code-Coverage für PHPUnit wird in PHPStorm über den Run-With-Coverage-Button ausgelöst – das grüne Play-Symbol mit Schild. PHPStorm aktiviert dabei automatisch Xdebug im Coverage-Modus und sammelt Zeilenabdeckungs-Daten während des Testlaufs. Voraussetzung: Xdebug muss mit xdebug.mode=debug,coverage konfiguriert sein. Der Coverage-Bericht erscheint nach dem Testlauf im Coverage-Panel und zeigt Klassen, Methoden und Zeilen mit farbiger Markierung direkt im Editor.
Grüne Zeilen sind durch mindestens einen Test abgedeckt, rote Zeilen sind ungetestet, gelbe Zeilen sind teilweise abgedeckt (zum Beispiel ein Branch einer if-Abfrage). PHPStorm kann auch HTML-Coverage-Berichte als separate Dateien exportieren: Run → Generate Coverage Report. Diese Berichte eignen sich für CI-Artefakte und Code-Reviews. Wichtig: Coverage-Messung verlangsamt den Testlauf erheblich – für schnelle Feedback-Zyklen Tests ohne Coverage starten, Coverage nur für Analyse-Läufe aktivieren.
6. Einzelne Tests und Methoden direkt aus dem Editor starten
Einer der größten Vorteile der PHPStorm-Integration: PHPUnit-Testmethoden können direkt aus dem Code-Editor gestartet werden. Im Editorfenster erscheint neben jeder Testklasse und Testmethode ein grünes Play-Symbol in der Zeilennummerleiste. Klick darauf startet genau diesen Test mit der letzten aktiven Run-Konfiguration. Rechtsklick bietet zusätzlich Debug an, was Breakpoints in der Testmethode und im getesteten Code aktiviert.
Mit Ctrl+Shift+T springt PHPStorm von einer Klasse zu ihrer Testklasse und zurück. Das ist besonders nützlich beim Test-Driven-Development-Ansatz: Testklasse schreiben, Code schreiben, mit einem Tastendruck zwischen beiden wechseln. PHPStorm erstellt fehlende Testklassen auch automatisch über Navigate → Test und legt dabei die korrekte Verzeichnisstruktur (Test/Unit/, Test/Integration/) automatisch an, wenn das Modul-Namespacing korrekt konfiguriert ist.
7. Eine vollständige Magento-Integrationstest-Klasse schreiben
Magento-Integrationstests unterscheiden sich von Unit-Tests durch den Zugriff auf den ObjectManager, die Datenbank und den gesamten Magento-Kernel. Der ObjectManager-Zugriff funktioniert über Magento\TestFramework\Helper\Bootstrap::getObjectManager(). Das @magentoDbIsolation enabled-Annotation sorgt dafür, dass alle Datenbankoperationen in einer Transaktion laufen und nach dem Test zurückgerollt werden. Mit @magentoDataFixture können Testdaten aus Fixture-Dateien geladen werden.
Ein häufiger Fehler beim Schreiben von Integrationstests: Services mit new Klasse() instanziieren statt über den ObjectManager. Das umgeht die Magento-DI und führt zu Fehlern, weil Abhängigkeiten fehlen. Korrekt ist $this->objectManager->get(ServiceInterface::class) oder $this->objectManager->create(ServiceInterface::class). get gibt die Singleton-Instanz zurück, create erzeugt immer eine neue Instanz – je nach Test-Anforderung die richtige Wahl treffen.
<?php
declare(strict_types=1);
namespace Mironsoft\Catalog\Test\Integration\Model;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\TestCase\AbstractIntegrationTestCase;
use Mironsoft\Catalog\Api\ProductEnricherInterface;
use Mironsoft\Catalog\Model\ProductEnricher;
/**
* Integration test for ProductEnricher service.
*
* @magentoDbIsolation enabled
* @magentoAppIsolation enabled
*/
class ProductEnricherTest extends AbstractIntegrationTestCase
{
private ProductEnricherInterface $enricher;
protected function setUp(): void
{
parent::setUp();
$this->enricher = Bootstrap::getObjectManager()->get(ProductEnricherInterface::class);
}
/**
* @magentoDataFixture Mironsoft_Catalog::Test/Integration/_files/simple_product.php
*/
public function testEnrichAddsExpectedAttributes(): void
{
$productId = 1;
$result = $this->enricher->enrich($productId);
self::assertNotNull($result, 'Enriched product must not be null');
self::assertTrue($result->hasCustomAttribute('mironsoft_enriched'));
self::assertEquals('1', $result->getCustomAttribute('mironsoft_enriched')->getValue());
}
/**
* @magentoDataFixture Mironsoft_Catalog::Test/Integration/_files/simple_product.php
*/
public function testEnrichThrowsForInvalidProduct(): void
{
$this->expectException(\InvalidArgumentException::class);
$this->enricher->enrich(99999);
}
}
8. Unit- vs. Integrationstests im Vergleich
Die Wahl zwischen Unit- und Integrationstests in Magento ist keine dogmatische Entscheidung, sondern hängt davon ab, was getestet werden soll. Geschäftslogik ohne Datenbankzugriff gehört in Unit-Tests. Repositories, Events, Plugins und Commands, die mit der Magento-Infrastruktur interagieren, gehören in Integrationstests. Beiden Testarten gemeinsam ist der PHPUnit-Rahmen und die PHPStorm-Integration – der Unterschied liegt in Laufzeit, Infrastrukturanforderungen und Testtiefe.
| Kriterium | Unit-Test | Integrationstest | Empfehlung |
|---|---|---|---|
| Laufzeit | Millisekunden | Sekunden bis Minuten | Unit-Tests im Entwicklungsflow |
| Datenbankzugriff | Kein (Mocks) | Ja, dedizierte DB | Repositories → Integrationstest |
| Magento-Bootstrap | Nicht nötig | Vollständig | DI/Plugin-Verhalten → Integrationstest |
| Coverage-Tiefe | Klassen-intern | Module-übergreifend | Beide für vollständige Coverage |
| PHPStorm-Start | Sofort aus Editor | Run-Config nötig | Beide über PHPStorm steuerbar |
Die praktische Empfehlung: Unit-Tests decken die Geschäftslogik der Value Objects, Calculator-Klassen und Service-Implementierungen ab. Integrationstests prüfen, ob Plugins korrekt ausgelöst werden, ob Repository-Methoden die richtigen Daten persistieren und ob Events die erwarteten Observer aufrufen. Beide Testarten ergänzen sich – wer nur Unit-Tests hat, testet die Integration nicht; wer nur Integrationstests hat, hat zu langsame Feedback-Zyklen.
9. Typische Fehler und ihre Ursachen
Der häufigste Fehler beim ersten Start von Integrationstests aus PHPStorm: Error: Class not found für Magento-Klassen. Ursache: das Working Directory der Run-Konfiguration zeigt nicht auf das Magento-Root, oder der Autoloader wurde nicht korrekt eingebunden. Lösung: Working Directory in der Run-Konfiguration auf /var/www/html (Container-Pfad) setzen und sicherstellen, dass die phpunit.xml den richtigen Bootstrap-Pfad enthält.
Ein weiterer häufiger Fehler: Datenbankverbindung schlägt fehl. Die Fehlermeldung enthält oft Connection refused auf Host localhost. Ursache: die install-config-mysql.php enthält localhost statt db (Docker-Service-Name). Im Container ist der MySQL-Host der Service-Name aus dem Compose-File, nicht localhost. Nach der Korrektur muss der Integration-Test-Bootstrap neu ausgeführt werden – PHPStorm bietet dafür die Option Invalidate Caches and Restart im File-Menü.
10. Zusammenfassung
PHPUnit-Integrationstests für Magento aus PHPStorm zu starten erfordert vier Schritte: Testdatenbank anlegen und install-config-mysql.php mit Container-internen Zugangsdaten befüllen, phpunit.xml mit eigenem Testsuite-Filter anpassen, Run-Konfigurationen in PHPStorm mit Remote-Interpreter und korrektem Working Directory anlegen, und Xdebug im Coverage-Modus aktivieren. Jeder Schritt ist einmalig pro Projekt – danach laufen Tests mit einem Klick oder Tastendruck direkt aus der IDE.
Der Mehrwert ist dauerhaft: Coverage-Berichte zeigen sofort, welche Zeilen im eigenen Modul ungetestet sind. Einzelne Tests können mit Breakpoints debuggt werden, ohne ein Terminal zu öffnen. Das Wechseln zwischen Implementierung und Testklasse mit Ctrl+Shift+T beschleunigt den TDD-Workflow erheblich. In Magento-Projekten, wo Module komplex miteinander interagieren, ist die IDE-gestützte Testausführung kein Komfort, sondern ein fundamentales Qualitätssicherungswerkzeug.
PHPUnit + Magento in PHPStorm — Das Wichtigste auf einen Blick
Testdatenbank
magento_integration_tests anlegen. install-config-mysql.php mit Docker-Service-Namen db als Host konfigurieren, nicht localhost.
Run-Konfiguration
Remote-Interpreter (phpfpm), Working Directory /var/www/html, Konfigurationsdatei dev/tests/integration/phpunit.xml.
Coverage
xdebug.mode=debug,coverage. Run-With-Coverage-Button aktiviert Coverage automatisch. Bericht erscheint inline im Editor.
Einzeltest
Play-Symbol neben Testmethode startet genau diesen Test. Ctrl+Shift+T wechselt zwischen Klasse und Testklasse.
Mironsoft
Magento-Testing, Code-Qualität und PHPStorm-Integration
Magento-Tests in PHPStorm einrichten?
Wir richten Unit- und Integrationstests für euer Magento-Modul ein – mit Coverage-Berichten, Run-Konfigurationen und vollständiger PHPStorm-Integration.
Test-Setup
Testdatenbank, phpunit.xml und Run-Konfigurationen für euer Magento-Projekt einrichten
Test-Entwicklung
Unit- und Integrationstests für bestehende Module schreiben und Coverage erhöhen
CI-Integration
PHPUnit in GitHub Actions oder GitLab CI mit Coverage-Reporting integrieren