Sind Ihre Tests eine Illusion von Sicherheit?
Stellen Sie sich vor: Sie haben 95% Codeabdeckung, alle Tests sind grün, CI/CD läuft durch. Sie sind überzeugt, dass Ihr PHP-Code vor Regressionen geschützt ist. Aber ist das wirklich so?
Ich selbst lebte lange Zeit in dieser Illusion, bis ich auf eine Situation stieß: Ein Test bestand, obwohl ich versehentlich && durch || in einer kritischen Bedingung ersetzt hatte. Der Test prüfte diesen Zweig einfach nicht. Die Abdeckung lag bei 100%, die Logik jedoch nicht.
Lernen Sie kennen: Mutationstests (mutation testing) – eine Methode, die Ihre Tests gnadenlos „tötet“, um herauszufinden, wie zuverlässig sie wirklich sind. In diesem Artikel sehen wir uns an, wie Sie sie in PHP mit dem leistungsstarken Tool Infection anwenden und warum dies die Spielregeln ändert.
Was sind Mutationstests und warum werden sie benötigt?
Mutationstests sind ein Ansatz, bei dem kleine absichtliche Änderungen (Mutationen) in Ihren Quellcode eingefügt werden. Zum Beispiel wird der Operator + durch - ersetzt, true durch false oder eine ganze Zeile gelöscht. Nach jeder Mutation werden Ihre Tests ausgeführt.
Wenn der Test fehlschlägt – wurde die Mutation „getötet“, bedeutet das, dass der Test diesen Codeabschnitt tatsächlich prüft. Wenn der Test bestanden wird – hat die Mutation „überlebt“. Das ist ein alarmierendes Signal: Entweder prüft der Test diese Bedingung nicht, oder er ist falsch geschrieben.
Im Gegensatz zur Metrik „Codeabdeckung“ (code coverage), die nur anzeigt, welche Zeilen ausgeführt wurden, prüfen Mutationstests die Qualität der Prüfungen. Eine hohe Abdeckung ist keine Garantie, aber der Mutations-Score (Mutation Score Indicator, MSI) ist ein echter Indikator für Zuverlässigkeit.
Warum ist das für PHP-Entwickler wichtig?
- Aufdeckung „toter“ Tests – solche, die immer grün sind, aber nichts prüfen.
- Identifikation von Lücken in der Logik – z.B. übersehene Randbedingungen.
- Erhöhte Sicherheit beim Refactoring – Sie wissen genau, welche Tests den Code schützen.
- Zeitersparnis – statt manueller Testaudits erhalten Sie einen automatischen Bericht.
Tools für Mutationstests in PHP
Der Spitzenreiter auf der PHP-Bühne ist Infection (früher bekannt als Humbug). Es lässt sich leicht in PHPUnit und Pest integrieren, unterstützt viele Mutationen und liefert anschauliche Berichte.
Andere Optionen: Humbug (der Vorläufer, aber weniger aktiv) und Mutagen (experimentell). Wir konzentrieren uns auf Infection – das ist der moderne Standard.
Praxis: Infection im Projekt einrichten
Lassen Sie uns Infection installieren und an einem realen Beispiel ausführen. Angenommen, wir haben eine einfache Klasse zur Berechnung eines Rabatts:
<?php// src/DiscountCalculator.phpclass DiscountCalculator{ public function calculate(float $price, bool $isPremium): float { if ($isPremium) { return $price * 0.9; // 10% Rabatt }
return $price; }}Und den dazugehörigen Test:
<?php// tests/DiscountCalculatorTest.phpuse PHPUnit\\Framework\\TestCase;
class DiscountCalculatorTest extends TestCase{ public function testPremiumDiscount(): void { $calculator = new DiscountCalculator(); $result = $calculator->calculate(100.0, true); $this->assertEquals(90.0, $result); }
public function testRegularPrice(): void { $calculator = new DiscountCalculator(); $result = $calculator->calculate(100.0, false); $this->assertEquals(100.0, $result); }}Die Abdeckung beträgt 100%. Aber lassen Sie uns mit Mutationen prüfen.
Installation und Ausführung von Infection
composer require --dev infection/infection./vendor/bin/infectionNach