Kodokon kodokon.com

Qualität: PHPUnit, PHPStan und die PSRs

Rüste deinen Code wie ein Profi aus: mit PHPUnit-Tests, statischer Analyse durch PHPStan auf Level 9 und den PSR-Standards.

10 Min. · 3 Fragen

Diese Lektion in Kodokon öffnen

Code auf Expertenniveau erkennt man weniger an cleveren Tricks als an seinem Sicherheitsnetz. Drei sich ergänzende Säulen: Tests (PHPUnit), die das Verhalten überprüfen, indem sie den Code ausführen, statische Analyse (PHPStan), die Eigenschaften beweist, ohne irgendetwas auszuführen, und gemeinsame Standards (PSR), die das Ökosystem interoperabel machen. Alles installierst du mit Composer, als Entwicklungsabhängigkeiten.

BASH
composer require --dev phpunit/phpunit
composer require --dev phpstan/phpstan
./vendor/bin/phpunit --testdox tests
./vendor/bin/phpstan analyse src --level=9
Die Option --testdox zeigt die Tests als lesbare Spezifikation an.

Seit PHPUnit 10 werden die Metadaten als PHP-Attribute geschrieben: #[DataProvider] ersetzt die Docblock-Annotation @dataProvider. Ein Data Provider muss public und statisch sein, weil PHPUnit ihn liest, noch bevor die Testklasse instanziiert wird. Jeder Datensatz trägt einen beschreibenden Schlüssel, der bei einem Fehlschlag unverändert angezeigt wird - ein Fehlschlag bei accents ist sofort lokalisiert.

PHP
<?php
declare(strict_types=1);

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

final class SlugifierTest extends TestCase
{
    #[DataProvider('provideTitles')]
    public function testSlugify(
        string $input,
        string $expected
    ): void {
        $this->assertSame($expected, slugify($input));
    }

    public static function provideTitles(): array
    {
        return [
            'simple' => [
                'Hello World', 'hello-world'
            ],
            'accents' => [
                'Déjà vu', 'deja-vu'
            ],
        ];
    }
}
Testet eine Funktion slugify, die anderswo in deinem Projekt definiert ist.

PHPStan staffelt seine Strenge in Levels von 0 bis 9 (in neueren Versionen gibt es ein Level 10): Auf Level 9 wird jeder mixed-Wert unbrauchbar, solange er nicht durch ausdrückliche Prüfungen eingegrenzt wurde. Seine wahre Stärke kommt von den Docblock-Typen, die die PHP-Engine ignoriert, der Analysator aber überprüft: Array-Formen array{email: string}, Listen list<int>, Generics. Sie dokumentieren und beweisen zugleich.

PHP
<?php
declare(strict_types=1);

function findEmail(?array $user): string
{
    return $user['email'];
}

/**
 * @param array{email: string}|null $user
 */
function findEmailSafe(?array $user): string
{
    return $user === null
        ? 'n/a'
        : $user['email'];
}
Level 9: Die erste Funktion wird abgelehnt (möglicher Zugriff auf null, unbekannter Schlüssel und Typ), die zweite geht durch.

Die PSRs (PHP Standards Recommendations) sind die Konventionen der PHP-FIG. PSR-1 und PSR-12 vereinheitlichen den Stil: Einrückung, geschweifte Klammern, Reihenfolge der Imports - automatisch angewendet von php-cs-fixer oder phpcs. PSR-4 definiert das Autoloading: Ein Namespace-Präfix wird auf ein Verzeichnis abgebildet, wodurch Composer jede Klasse ohne manuelles require finden kann. Und schließlich erlauben dir die Interface-PSRs - PSR-3 für Logger, PSR-7 für HTTP-Nachrichten -, eine Bibliothek gegen eine andere zu tauschen, ohne den Code anzufassen, der sie nutzt.

Wissenscheck

Stelle sicher, dass du die wichtigsten Punkte dieser Lektion behalten hast.

  1. Welche Einschränkung gilt seit PHPUnit 10 für eine Data-Provider-Methode, auf die #[DataProvider] verweist?
    • Sie muss public und statisch sein, weil PHPUnit sie liest, bevor die Testklasse instanziiert wird
    • Sie muss einen Generator zurückgeben, niemals ein Array
    • Sie muss denselben Namen wie der Test tragen, mit dem Suffix Provider
  2. Was schreibt PHPStan Level 9 vor?
    • Docblocks zu verbieten, zugunsten ausschließlich nativer Typen
    • Eine strenge Behandlung von mixed: Du kannst einen solchen Wert nicht verwenden, ohne ihn vorher einzugrenzen
    • 100 % Testabdeckung des analysierten Codes
  3. Was definiert der Standard PSR-4?
    • Das Format der Logmeldungen einer Anwendung
    • Die Zuordnung zwischen einem Namespace-Präfix und einem Verzeichnis, genutzt vom Autoloader von Composer
    • Den Einrückungsstil und die Platzierung der geschweiften Klammern