was Unit, Integration und MFTF jeweils leisten
Die häufigste Fehlinvestition in der Testautomatisierung: zu viele langsame End-to-End-Tests und zu wenige schnelle Unit-Tests. Die Test-Pyramide gibt die richtige Gewichtung vor – drei Stufen mit klar getrennten Aufgaben, die zusammen eine zuverlässige Teststrategie ergeben.
Inhaltsverzeichnis
- 1. Das Konzept der Test-Pyramide für Magento
- 2. Unit-Tests: die Basis der Pyramide
- 3. Integrationstests: das Zusammenspiel prüfen
- 4. MFTF: End-to-End im Browser
- 5. Das richtige Verhältnis der Teststufen
- 6. Infrastrukturaufwand pro Teststufe
- 7. Test-Pyramide in der CI/CD-Pipeline
- 8. Anti-Patterns: die umgekehrte Pyramide
- 9. Direkter Vergleich der drei Teststufen
- 10. Zusammenfassung
- 11. FAQ
1. Das Konzept der Test-Pyramide für Magento
Die Test-Pyramide ist ein Modell, das die Verteilung von Tests nach Geschwindigkeit, Isolationsgrad und Infrastrukturaufwand beschreibt. An der Basis stehen viele schnelle Unit-Tests, in der Mitte weniger Integrationstests, an der Spitze wenige End-to-End-Tests. Für Magento 2 bedeutet das konkret: Unit-Tests mit PHPUnit ohne Bootstrap, Integrationstests mit vollem Magento-Bootstrap und Datenbankzugang, MFTF-Tests mit Browser-Automatisierung gegen eine vollständige Magento-Installation.
Das Modell ist kein Dogma, sondern eine Orientierung. In Magento-Projekten, die stark datenbankgetrieben sind, verschiebt sich der Schwerpunkt etwas in Richtung Integrationstests – weil viele Kernfunktionen nur mit echten Datenbankoperationen sinnvoll getestet werden können. Trotzdem bleibt die Grundregel: schnelle, isolierte Tests dominieren die Basis, langsame, infrastrukturintensive Tests bleiben an der Spitze.
Ein häufiger Fehler in Magento-Projekten ist das Fehlen einer expliziten Teststrategie. Tests entstehen ad hoc, meistens als Integrations- oder MFTF-Tests, weil sie die sichtbaren Ergebnisse direkt prüfen. Das Ergebnis ist eine umgekehrte Pyramide – viele langsame Tests, die bei jedem Merge mehrere Minuten laufen, und keine Unit-Tests, die in Sekunden Feedback geben. Die Test-Pyramide gibt das richtige Gegengewicht vor.
2. Unit-Tests: die Basis der Pyramide
Unit-Tests in Magento 2 laufen unter dev/tests/unit/ mit einem minimalen Bootstrap, der nur den Autoloader aktiviert. Alle Abhängigkeiten der getesteten Klasse werden durch PHPUnit-Mocks ersetzt. Das Ergebnis: eine Test-Suite mit hundert Tests, die in unter fünf Sekunden durchläuft – ohne Datenbankverbindung, ohne Magento-Instanz, ohne Browser. Dieser Geschwindigkeitsvorteil ist der Hauptgrund, warum Unit-Tests die Basis der Pyramide bilden.
Was Unit-Tests in Magento abdecken: die Logik von ViewModels, Services und Helpers, Exception-Handling in Repositories, Berechnungslogik in Preis-Modellen, Validierungsregeln in Data-Transfer-Objects. Was sie nicht abdecken: Datenbankinteraktionen, Event-Dispatching mit echten Observern, Layout-Rendering, Session-Handling. Diese klare Grenze ist wichtig – wer sie missachtet und Datenbankoperationen im Unit-Test mocken will, baut Mocks, die die echte Implementierung nur vortäuschen.
<?php
// File: dev/tests/unit/phpunit.xml (relevant excerpt)
// Unit tests: no database, no full Magento bootstrap
// Run: vendor/bin/phpunit -c dev/tests/unit/phpunit.xml \
// --testsuite=Mironsoft_Catalog
// Typical unit test execution time: < 5 seconds for 100 tests
// Coverage: business logic, exception handling, calculation logic
// Integration test phpunit.xml is at: dev/tests/integration/phpunit.xml
// Integration tests require: running database, Magento install, fixtures
// Typical execution time: 30 seconds to several minutes
// MFTF: dev/tests/acceptance/
// Requires: full Magento stack, Selenium/WebDriver, browser
// Typical execution time: minutes per scenario
// The ratio in a healthy Magento project:
// Unit: 70% of all tests
// Integration: 25% of all tests
// MFTF/E2E: 5% of all tests (critical user journeys only)
3. Integrationstests: das Zusammenspiel prüfen
Magento-Integrationstests unter dev/tests/integration/ verwenden einen vollständigen Bootstrap mit eigener Test-Datenbank und aktivem DI-Container. Sie testen, ob Klassen im echten Magento-Kontext korrekt zusammenarbeiten: ob ein Repository wirklich die richtigen Einträge aus der Datenbank liest, ob ein Plugin den Methodenaufruf korrekt modifiziert, ob ein Observer nach einem Event den erwarteten Seiteneffekt erzeugt. Das ist die Teststufe, die Dinge aufdeckt, die Unit-Tests mit Mocks verbergen.
Integrationstests in Magento nutzen Fixtures – PHP-Skripte, die Testdaten in die Datenbank schreiben und nach dem Test wieder entfernen. Das @magentoDataFixture-Attribut verweist auf diese Fixture-Datei und stellt sicher, dass der Test in einem definierten Datenbankzustand läuft. Dieser Mechanismus macht Integrationstests wiederholbar und isoliert voneinander, auch wenn sie gegen dieselbe Datenbank laufen. Der Nachteil: jeder Datenbankzugriff kostet Zeit, was Integrationstests um Größenordnungen langsamer als Unit-Tests macht.
<?php
// File: app/code/Mironsoft/Catalog/Test/Integration/Model/ProductRepositoryTest.php
declare(strict_types=1);
namespace Mironsoft\Catalog\Test\Integration\Model;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\Framework\Exception\NoSuchEntityException;
use Mironsoft\Catalog\Api\ProductRepositoryInterface;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\Test;
/**
* Integration test: uses real database, real DI container.
* Fixture creates test product before each test, rolls back after.
*/
class ProductRepositoryTest extends TestCase
{
private ProductRepositoryInterface $repository;
protected function setUp(): void
{
$objectManager = Bootstrap::getObjectManager();
$this->repository = $objectManager->get(ProductRepositoryInterface::class);
}
#[Test]
#[\Magento\TestFramework\Annotation\DataFixture(
'Mironsoft_Catalog::Test/Integration/_files/product_enabled.php'
)]
public function getByIdReturnsRealProductFromDatabase(): void
{
// This test actually queries the database — no mocks
$product = $this->repository->getById(1);
$this->assertSame('test-product-sku', $product->getSku());
$this->assertTrue((bool)$product->getStatus());
}
#[Test]
public function getByIdThrowsExceptionForNonExistentId(): void
{
$this->expectException(NoSuchEntityException::class);
$this->repository->getById(99999);
}
}
4. MFTF: End-to-End im Browser
Das Magento Functional Testing Framework (MFTF) automatisiert Browser-Tests gegen eine vollständige Magento-Installation. MFTF-Tests simulieren echte Nutzerinteraktionen: Produkt in den Warenkorb legen, Checkout durchführen, Admin-Panel navigieren, Formulare ausfüllen. Sie prüfen das Gesamtsystem aus Nutzerperspektive und decken Integrationsbrüche auf, die weder Unit- noch Integrationstests finden können – zum Beispiel wenn ein JavaScript-Fehler den Checkout-Button deaktiviert.
MFTF-Tests sind in XML geschrieben und folgen dem Page-Object-Pattern. Jede Seite hat eine XML-Datei, die die Selektoren definiert, und jeder Test beschreibt die Schritte als XML-Actions. Das klingt nach viel Overhead, hat aber einen Vorteil: MFTF-Tests können von QA-Mitarbeitern ohne PHP-Kenntnisse geschrieben und angepasst werden. Der Nachteil ist die Ausführungsgeschwindigkeit – ein einziger MFTF-Test kann Minuten dauern, weil er auf Seitenladungen, JavaScript-Ausführung und Browser-Rendering wartet.
5. Das richtige Verhältnis der Teststufen
Eine gesunde Testpyramide für ein Magento-Custommodul hat ungefähr dieses Verhältnis: 70% Unit-Tests, 25% Integrationstests, 5% MFTF-Tests. Das bedeutet in der Praxis: jede Methode mit nichttrivialer Logik bekommt einen Unit-Test, kritische Datenbankoperationen bekommen einen Integrationstest, und die wichtigsten Nutzer-Journeys – Checkout, Login, Produktsuche – bekommen einen MFTF-Test.
Dieses Verhältnis ist kein absolutes Gesetz. Ein Modul, das primär Datenmigration durchführt, braucht mehr Integrationstests als ein Modul, das nur Preisberechnungen implementiert. Ein Modul, das komplexe Frontend-Interaktionen steuert, braucht mehr MFTF-Tests als ein reines Backend-Modul. Die Test-Pyramide ist das Ziel, die tatsächliche Gewichtung hängt vom Modultyp ab. Was immer gilt: MFTF-Tests sind am teuersten in Erstellung und Wartung und sollten die Ausnahme bleiben.
6. Infrastrukturaufwand pro Teststufe
Unit-Tests benötigen nur PHP, Composer und PHPUnit – sie laufen in jeder Umgebung, die einen PHP-Interpreter hat. Integrationstests benötigen eine vollständige Magento-Datenbank (typischerweise eine separate Test-Datenbank) und einen Magento-Install ohne aktive Caches. MFTF-Tests benötigen zusätzlich einen Browser-Treiber (Chrome + ChromeDriver oder Selenium Grid), eine vollständige Magento-Installation mit aktivem Frontend und MFTF-Konfiguration in .env.testing.
In einer Docker-basierten Entwicklungsumgebung wie Mark Shust's Setup laufen Unit-Tests und Integrationstests direkt im PHP-Container. MFTF-Tests erfordern zusätzliche Container für Selenium. Das erhöht den Infrastrukturaufwand spürbar – sowohl lokal als auch in der CI-Pipeline. Dieser Aufwand rechtfertigt sich nur für die kritischsten End-to-End-Szenarien.
7. Test-Pyramide in der CI/CD-Pipeline
In einer gut konfigurierten CI-Pipeline laufen die drei Teststufen gestaffelt: Unit-Tests laufen bei jedem Commit und geben innerhalb von Sekunden Feedback. Integrationstests laufen bei jedem Pull-Request-Merge gegen den Hauptbranch und geben innerhalb von Minuten Feedback. MFTF-Tests laufen einmal täglich oder vor einem Release und geben innerhalb von zehn bis dreißig Minuten Feedback. Diese Staffelung stellt sicher, dass Entwickler schnelles Feedback für alltägliche Änderungen bekommen und die teuren Tests nicht den Entwicklungsfluss verlangsamen.
Eine typische GitHub-Actions-Konfiguration für Magento hat separate Jobs für die drei Teststufen. Der Unit-Test-Job läuft parallel zum Linting und PHPStan. Der Integrations-Test-Job startet erst, wenn der Unit-Test-Job erfolgreich war – als Gate. Der MFTF-Job läuft nur auf dem Hauptbranch oder auf Release-Branches. Dieses Setup gibt den Entwicklern täglich produktives Feedback, ohne die CI-Pipeline mit langen Wartezeiten zu blockieren.
8. Anti-Patterns: die umgekehrte Pyramide
Das häufigste Anti-Pattern in Magento-Projekten ist die umgekehrte Pyramide: viele MFTF-Tests, wenige Integrationstests, keine Unit-Tests. Das entsteht oft, weil MFTF-Tests sichtbare Ergebnisse prüfen und leicht zu verstehen sind – der Tester sieht im Video, wie der Bot durch den Checkout navigiert. Unit-Tests dagegen testen abstrakte Logik und erfordern ein gutes Verständnis der Klassen. Der Preis für die umgekehrte Pyramide ist eine CI-Pipeline, die dreißig Minuten läuft und bei jedem flaky MFTF-Test falsch-negativ schlägt.
Ein zweites Anti-Pattern ist der übermäßige Einsatz von Integrationstests für Logik, die sich mit Unit-Tests abdecken ließe. Wenn ein Entwickler jeden Service mit einem Integrationstest prüft, weil er sich nicht mit Mocking beschäftigen will, entstehen langsame Tests, die bei Datenbankfehlern scheitern, ohne dass sich die Geschäftslogik geändert hat. Das untergräbt das Vertrauen in die Test-Suite.
| Kriterium | Unit-Test | Integrationstest | MFTF |
|---|---|---|---|
| Ausführungszeit | Millisekunden | Sekunden | Minuten |
| Infrastrukturbedarf | Nur PHP + PHPUnit | DB + Magento | Browser + volles Stack |
| Flakiness-Risiko | Sehr gering | Mittel | Hoch |
| Abgedeckter Bereich | Logik einer Klasse | Modul + Datenbank | Gesamtes System |
| Wartungsaufwand | Gering | Mittel | Hoch |
10. Zusammenfassung
Die Magento 2 Test-Pyramide beschreibt, wie Unit-Tests, Integrationstests und MFTF-Tests zueinander stehen und welche Aufgabe jede Stufe hat. Unit-Tests bilden die breite Basis: schnell, isoliert, ohne Infrastruktur. Integrationstests prüfen das Zusammenspiel mit Datenbank und DI-Container. MFTF-Tests prüfen kritische Nutzer-Journeys im Browser. Das optimale Verhältnis ist 70% Unit, 25% Integration, 5% MFTF – je nach Modultyp mit Verschiebungen.
Wer die Pyramide umdreht und hauptsächlich MFTF-Tests schreibt, zahlt mit langen CI-Laufzeiten, hohem Wartungsaufwand und flaky Tests. Wer sie korrekt aufbaut, bekommt schnelles Feedback bei jedem Commit, zuverlässige Integrationsprüfung bei jedem Merge und E2E-Absicherung für die wichtigsten Prozesse.
Magento 2 Test-Pyramide — Das Wichtigste auf einen Blick
Unit-Tests
Basis der Pyramide. dev/tests/unit/ ohne DB. Millisekunden pro Test. Logik, Exception-Handling, Berechnungen. 70% der Tests.
Integrationstests
Mitte der Pyramide. Echte DB, voller Magento-Bootstrap. Fixtures. Datenbank-Queries, Plugin-Verhalten, Events. 25% der Tests.
MFTF
Spitze der Pyramide. Browser + volles Stack. Minuten pro Test. Kritische User-Journeys. 5% der Tests – nur für das Wesentliche.
CI-Staffelung
Unit bei jedem Commit. Integration bei jedem PR-Merge. MFTF täglich oder vor Release. Gestaffeltes Feedback, minimale Wartezeit.
Mironsoft
Magento 2 Teststrategie, PHPUnit und MFTF-Automatisierung
Teststrategie für euer Magento-Projekt aufbauen?
Wir analysieren bestehende Testlücken, bauen eine an die Projektstruktur angepasste Test-Pyramide auf und integrieren alle drei Teststufen in die CI/CD-Pipeline.
Strategie-Audit
Analyse der bestehenden Testlandschaft und Empfehlungen für die richtige Pyramide
Test-Implementierung
Unit-, Integrations- und MFTF-Tests für kritische Magento-Module aufbauen
CI-Pipeline
Gestaffelte Test-Jobs in GitHub Actions oder GitLab CI einrichten