NCA Social Media
PHPUnit Logo

Was ist PHPUnit? Das Testing-Framework für PHP

PHPUnit ist das Standard-Framework für automatisierte Tests in PHP. Seit über 20 Jahren bildet es das Rückgrat der Qualitätssicherung in PHP-Projekten. Entwickelt von Sebastian Bergmann, hilft das Open-Source-Tool dabei, Code-Qualität abzusichern, Regressionen früh zu erkennen und Refactorings ohne Angst durchzuführen.

Anfang Februar 2026 ist Version 13 erschienen. Die spannendste Neuerung: Sealed Test Doubles, mit denen sich Mock-Konfigurationen abschließen lassen. Dazu kommen bessere Array-Vergleiche und ein klarerer Umgang mit Test-Intentionen. Dieser Leitfaden deckt alles ab, von der Einrichtung bis zu fortgeschrittenen Techniken.

Das Framework folgt der xUnit-Architektur und passt in jeden modernen Workflow: lokale Entwicklung, CI/CD-Pipelines, automatisiertes Deployment. Egal ob Symfony, Laravel oder Sulu CMS, ohne vernünftige Tests geht 2026 wenig.

CYPRESS.IO Ambassador und IT Consultant für QA Engenieering und Qualität in PHP Projekten.

Erreichen Sie unsere PHP Consultant Spezialisten

Wir sind Experten für PHP und helfen Ihnen, Ihre digitalen Herausforderungen zu meistern. Unser erfahrenes Team unterstützt Sie bei PHP Updates, PHP Refactoring und berät Sie remote zu allen Fragen rund um PHP. Mit unseren vollautomatischen CI/CD Deployments und einer robusten Docker-Infrastruktur bringen wir Ihre PHP-Projekte auf das nächste Level. Vertrauen Sie auf unsere Expertise für zuverlässige und skalierbare PHP-Lösungen.

Was ist neu in Version 13?

Das Release vom 6. Februar 2026 setzt PHP 8.4 voraus und bringt vier echte Verbesserungen mit:

  • Sealed Test Doubles: Mit seal() lässt sich ein Mock nach der Konfiguration "verriegeln". Danach geht nichts mehr drauf. Nicht konfigurierte Methoden werden bei Mock Objects direkt abgelehnt, stille Fehlschläge gehören damit der Vergangenheit an.
  • Bessere Array-Assertions: Statt sich mit assertEquals() und assertSame() herumzuschlagen, gibt es jetzt eigene Assertions für Arrays. Die unterscheiden sauber zwischen striktem/losem Vergleich, mit/ohne Keys und geordnet/ungeordnet.
  • withConsecutive()-Ersatz: Seit Version 10 war das eine offene Baustelle. Jetzt gibt es zwei neue Rules, die Parameter über mehrere Aufrufe hinweg prüfen können.
  • any() ist hard-deprecated: Macht auch Sinn, denn ein Mock soll Interaktionen prüfen. Wer any() nutzt, sagt eigentlich "ist mir egal" und sollte lieber einen Stub verwenden.
Code:
          

// Mock konfigurieren und versiegeln
$mock = $this->createMock(PaymentGateway::class);

$mock->expects($this->once())
    ->method('charge')
    ->with(99.99)
    ->willReturn(true);

// Ab hier ist die Konfiguration dicht
$mock->seal();

// Alles was nicht konfiguriert wurde, fliegt jetzt auf
$processor = new OrderProcessor($mock);
$processor->processOrder($order);

Wichtig vor dem Upgrade: Erst die Test-Suite unter PHPUnit 12.5 sauber durchlaufen lassen, ohne Deprecation-Warnungen. Was in 12 als hard-deprecated markiert war, ist in 13 komplett raus.

PHPUnit Installation und Einrichtung 2026

Die Installation von PHPUnit erfolgt über Composer als Dev-Dependency. Für PHPUnit 13 gelten folgende Systemvoraussetzungen:

  • PHP 8.4 oder höher (PHP 8.5 wird ebenfalls unterstützt)
  • Composer 2.x
  • PHP-Extensions: dom, json, libxml, mbstring, xml, xmlwriter
Code:
          

composer require --dev phpunit/phpunit ^13.0

Nach der Installation empfiehlt sich eine phpunit.xml im Projekt-Root. PHPUnit 13 nutzt ausschließlich PHP-Attributes statt Annotations – die Konfiguration bleibt davon unberührt:

Code:
          

&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br>&lt;phpunit bootstrap="vendor/autoload.php"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;colors="true"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cacheDirectory=".phpunit.cache"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;executionOrder="depends,defects"&gt;<br>&nbsp;&nbsp;&nbsp;&lt;testsuites&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;testsuite name="Unit"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;directory&gt;tests/Unit&lt;/directory&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/testsuite&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;testsuite name="Integration"&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;directory&gt;tests/Integration&lt;/directory&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/testsuite&gt;<br>&nbsp;&nbsp;&nbsp;&lt;/testsuites&gt;<br>&nbsp;&nbsp;&nbsp;&lt;source&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;include&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;directory&gt;src&lt;/directory&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/include&gt;<br>&nbsp;&nbsp;&nbsp;&lt;/source&gt;<br>&lt;/phpunit&gt;

Die Trennung in Unit- und Integrationstests ist Best Practice und ermöglicht gezielte Testläufe. Mit executionOrder="depends,defects" werden fehlgeschlagene Tests priorisiert – das spart Zeit im Entwicklungsalltag.

Migration von PHPUnit 12 auf PHPUnit 13

Der Upgrade-Pfad von PHPUnit 12 auf 13 ist klar definiert: Zunächst muss die Test-Suite unter PHPUnit 12.5 ohne Deprecation-Warnings laufen. Erst dann sollte das Upgrade auf Version 13 erfolgen. Die wichtigsten Breaking Changes im Überblick:

  • PHP 8.4 Pflicht: Projekte auf PHP 8.3 oder älter können PHPUnit 13 nicht nutzen
  • Entfernte Features: Alles, was in PHPUnit 12 hard-deprecated war, ist in 13 entfernt
  • any()-Matcher: Jetzt hard-deprecated – Migration zu spezifischen Matchern oder Test Stubs erforderlich
  • Annotations: Seit PHPUnit 12 komplett entfernt, nur noch PHP Attributes

Rector automatisiert einen Großteil der Migration. Das Tool konvertiert Annotations zu Attributes, passt veraltete API-Aufrufe an und modernisiert die Test-Syntax:

Code:
          

composer require --dev rector/rector
./vendor/bin/rector process tests/ --set phpunit

Nach der automatisierten Migration sollte jeder Test manuell geprüft werden – besonders bei komplexen Mock-Setups und Custom Assertions. Tipp: Die Migration in einem eigenen Branch durchführen und die CI/CD-Pipeline als Qualitätsgate nutzen.

"You should not even try to upgrade to PHPUnit 13 if you cannot run your test suite using PHPUnit 12.5 without getting deprecation warnings."

– Sebastian Bergmann, PHPUnit Release Announcement, phpunit.de, 6. Februar 2026

Unterstützung bei der Migration? Wir helfen bei der Aktualisierung eurer Test-Suite – von der Rector-Konfiguration bis zur CI/CD-Integration. Kostenlose Erstberatung vereinbaren.

PHPUnit Grundlagen: Der erste Test mit Attributes

Seit PHPUnit 12 sind PHP Attributes der einzige Weg, Metadaten an Tests zu binden. Die alte Annotation-Syntax (@test, @dataProvider) funktioniert nicht mehr. Ein einfacher Unit-Test in der aktuellen PHPUnit-13-Syntax:

Code:
          

use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\Attributes\CoversClass;

#[CoversClass(Calculator::class)]
class CalculatorTest extends TestCase
{
    #[Test]
    public function addsTwoNumbers(): void
    {
        // Arrange
        $calculator = new Calculator();

        // Act
        $result = $calculator->add(2, 3);

        // Assert
        $this->assertSame(5, $result);
    }

    #[Test]
    public function divideByZeroThrowsException(): void
    {
        $this->expectException(\DivisionByZeroError::class);

        $calculator = new Calculator();
        $calculator->divide(10, 0);
    }
}

Das AAA-Pattern (Arrange, Act, Assert) strukturiert jeden Test in drei klar getrennte Phasen. PHPUnit bietet zahlreiche Assertions für verschiedene Prüfszenarien:

  • assertSame() – strikte Typ- und Wertprüfung
  • assertEquals() – Wertgleichheit mit Typ-Coercion
  • assertTrue() / assertFalse() – Boolesche Prüfungen
  • assertInstanceOf() – Typprüfung für Objekte
  • assertCount() – Anzahl der Elemente prüfen

Best Practice: Aussagekräftige Methodennamen verwenden, die das erwartete Verhalten beschreiben. Statt testAdd besser addsTwoPositiveNumbers in Kombination mit dem #[Test]-Attribute.

Fortgeschrittene Techniken: Mocking, Data Providers und Sealed Doubles

Data Providers ermöglichen parametrisierte Tests – in PHPUnit 13 ausschließlich über das #[DataProvider]-Attribute:

Code:
          

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;

#[Test]
#[DataProvider('additionProvider')]
public function addsNumbers(int $a, int $b, int $expected): void
{
    $calc = new Calculator();
    $this->assertSame($expected, $calc->add($a, $b));
}

public static function additionProvider(): array
{
    return [
        'zero plus zero' => [0, 0, 0],
        'positive numbers' => [1, 2, 3],
        'negative numbers' => [-1, -2, -3],
    ];
}

Die klare Trennung zwischen Test Stubs und Mock Objects ist seit PHPUnit 12 verbindlich. PHPUnit 13 verschärft diese Trennung weiter durch Sealed Test Doubles:

  • createStub() – isoliert Abhängigkeiten, simuliert Rückgabewerte
  • createMock() – verifiziert Kommunikation zwischen Objekten
  • seal() – versiegelt die Konfiguration (NEU in PHPUnit 13)
Code:
          

#[Test]
public function sendsNotificationOnOrderCompletion(): void
{
    // Stub: Simuliert Datenbank-Rückgabe
    $repository = $this->createStub(OrderRepository::class);
    $repository->method('findById')
        ->willReturn(new Order(id: 42, total: 99.99));

    // Mock: Verifiziert, dass Notification gesendet wird
    $notifier = $this->createMock(NotificationService::class);
    $notifier->expects($this->once())
        ->method('send')
        ->with($this->stringContains('Bestellung #42'));

    // Sealed: Keine weiteren unerwarteten Aufrufe
    $notifier->seal();

    $service = new OrderService($repository, $notifier);
    $service->completeOrder(42);
}

Exception Testing prüft, ob Code korrekt auf Fehlerzustände reagiert. PHPUnit bietet dafür expectException() sowie expectExceptionMessage():

Code:
          

#[Test]
public function rejectsInvalidEmail(): void
{
    $this->expectException(\InvalidArgumentException::class);
    $this->expectExceptionMessage('Ungültige E-Mail-Adresse');

    new EmailAddress('keine-email');
}

PHPUnit in CI/CD-Pipelines integrieren

Automatisierte Tests entfalten ihren vollen Wert erst in einer CI/CD-Pipeline. Ob GitLab CI, GitHub Actions oder Jenkins – PHPUnit lässt sich in jeden Workflow einbinden. Hier zwei praxiserprobte Konfigurationen:

GitLab CI/CD

Code:
          

phpunit:
  stage: test
  image: php:8.4-cli
  before_script:
    - apt-get update && apt-get install -y git unzip libzip-dev
    - docker-php-ext-install zip
    - curl -sS https://getcomposer.org/installer | php
    - php composer.phar install --no-interaction
  script:
    - vendor/bin/phpunit --coverage-text --colors=never
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml

GitHub Actions

Code:
          

name: PHPUnit Tests
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        php: ['8.4', '8.5']
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: ${{ matrix.php }}
          coverage: xdebug
      - run: composer install --no-interaction
      - run: vendor/bin/phpunit --coverage-clover coverage.xml

Performance-Tipps für große Test-Suites:

  • --parallel für parallele Testausführung in mehreren Prozessen
  • Fixtures mit setUp()/tearDown() für wiederverwendbare Testdaten
  • Database Transactions statt Seed-Daten für saubere Isolation
  • Cache-Directory in der phpunit.xml aktivieren für schnellere Folgeläufe

PHPUnit Versionen und Support-Zeiträume

PHPUnit Version PHP-Anforderung Bugfix-Support bis
PHPUnit 13 (aktuell) PHP 8.4+ Februar 2028
PHPUnit 12 PHP 8.3+ Februar 2027
PHPUnit 11 PHP 8.2+ Eingestellt (seit 02/2026)
PHPUnit 10 und älter PHP 8.1+ Eingestellt

Fazit: Warum sich das Upgrade lohnt

Version 13 räumt auf. Die versiegelten Test Doubles fangen eine ganze Klasse von Fehlern ab, die vorher still durchliefen. Die neuen Array-Assertions machen Schluss mit mehrdeutigen Vergleichen. Und wer noch any() nutzt, bekommt jetzt einen klaren Hinweis, dass es bessere Wege gibt.

Wer noch auf Version 11 oder älter sitzt, sollte jetzt handeln. Der Weg über PHPUnit 12 als Zwischenschritt ist gut dokumentiert, und Rector nimmt einem den Großteil der Arbeit ab.

Du planst ein Upgrade oder willst eure Test-Strategie auf solide Beine stellen? Wir helfen bei der Migration, der CI/CD-Anbindung und beim Aufbau einer nachhaltigen Test-Architektur. Ruf uns an für eine kostenlose Erstberatung oder schreib an roland@nevercodealone.de.

Häufig gestellte Fragen (FAQ)

Von der Einrichtung über Sealed Doubles bis zur CI/CD-Anbindung: Hier findest du Antworten auf die häufigsten Fragen rund um das Testing-Framework.

Was ist PHPUnit und wofür wird es 2026 eingesetzt?

PHPUnit ist das Standard-Testing-Framework für PHP, entwickelt von Sebastian Bergmann. Es ermöglicht automatisierte Unit-, Integrations- und Funktionstests und ist 2026 in Version 13 das zentrale Werkzeug für Qualitätssicherung in PHP-Projekten – von Symfony über Laravel bis Sulu CMS.

Welche PHP-Version braucht PHPUnit 13 im Jahr 2026?

PHPUnit 13 erfordert mindestens PHP 8.4. Die einzigen aktiv unterstützten PHP-Versionen im Februar 2026 sind PHP 8.4 und PHP 8.5. Ältere PHP-Versionen können PHPUnit 12 (PHP 8.3+) oder PHPUnit 11 (PHP 8.2+) nutzen, erhalten aber keine Bugfixes mehr.

Was sind die wichtigsten Neuerungen von PHPUnit 13 im Jahr 2026?

Die vier Hauptneuerungen in PHPUnit 13 sind Sealed Test Doubles mit der seal()-Methode, neue spezialisierte Array-Assertions, ein Ersatz für das entfernte withConsecutive() sowie die Hard-Deprecation des any()-Matchers. Alle Änderungen zielen auf klarere Test-Intentionen.

Wie migriere ich 2026 von PHPUnit 12 auf PHPUnit 13?

Zuerst die Test-Suite unter PHPUnit 12.5 ohne Deprecation-Warnungen ausführen. Dann Rector für die automatisierte Migration nutzen und anschließend auf PHPUnit 13 upgraden. Manuelles Review ist besonders bei Mock-Setups und Custom Assertions wichtig.

Lohnt sich PHPUnit 2026 auch für kleine PHP-Projekte?

Ja, auch kleine Projekte profitieren von automatisierten Tests. PHPUnit sichert Refactorings ab, dokumentiert erwartetes Verhalten und fängt Regressionen frühzeitig ab. Der initiale Aufwand zahlt sich bereits bei der ersten größeren Code-Änderung aus.

Was ist der Unterschied zwischen Test Stubs und Mock Objects?

Test Stubs simulieren Abhängigkeiten und liefern vordefinierte Rückgabewerte – erstellt mit createStub(). Mock Objects verifizieren zusätzlich, dass bestimmte Methodenaufrufe stattfinden – erstellt mit createMock(). PHPUnit 13 erzwingt diese Trennung konsequent.

Was sind Sealed Test Doubles in PHPUnit 13?

Sealed Test Doubles werden mit der seal()-Methode versiegelt. Danach sind keine weiteren Konfigurationsänderungen möglich, und bei Mock Objects werden alle nicht explizit konfigurierten Methoden automatisch abgelehnt. Das verhindert unbeabsichtigte Interaktionen.

Wie funktionieren Data Providers in PHPUnit 13?

Data Providers werden ausschließlich über das #[DataProvider]-Attribute referenziert. Die Provider-Methode muss statisch sein und ein Array zurückgeben. Benannte Keys verbessern die Lesbarkeit der Testergebnisse erheblich.

Kann ich PHPUnit in meiner IDE nutzen?

Ja, alle gängigen PHP-IDEs unterstützen PHPUnit. PHPStorm bietet integrierte Testausführung, Code Coverage und Debug-Funktionalität. VS Code nutzt die PHP Test Explorer Extension. Auch Netbeans und Eclipse bieten PHPUnit-Integration.

Wie integriere ich PHPUnit in eine CI/CD-Pipeline?

PHPUnit lässt sich in jede CI/CD-Plattform einbinden. Für GitLab CI und GitHub Actions genügt ein PHP-Image mit Composer und der Befehl vendor/bin/phpunit. Code Coverage Reports können als Artefakte exportiert werden.

Was kostet professionelle Unterstützung bei der PHPUnit-Migration?

Never Code Alone bietet individuelle Beratung für PHPUnit-Migrationen, CI/CD-Integration und Test-Strategie. Kontaktieren Sie uns für eine kostenlose Erstberatung unter roland@nevercodealone.de oder telefonisch unter +49 176 24747727.

Welche PHPUnit-Version sollte ich für neue Projekte verwenden?

Für neue Projekte empfiehlt sich PHPUnit 13 in Kombination mit PHP 8.4 oder 8.5. Diese Kombination bietet den längsten Support-Zeitraum bis Februar 2028 und alle aktuellen Features wie Sealed Test Doubles und die neuen Array-Assertions.