Eine grüne Testsuite beruhigt. Alle Tests bestanden, also muss der Code stimmen. Aber eine bestandene Suite sagt dir nur, dass nichts kaputt ist, was die Tests prüfen. Über das, was sie nie prüfen, sagt sie nichts. Also testen wir die Tests, indem wir unseren eigenen Code absichtlich kaputt machen.
Ein Test, der nicht scheitern kann, ist kein Test
Stell dir eine Regel vor: Wer ein Konto haben will, muss sechzehn sein. Jemand schreibt den Code und einen Test dazu. Der Test prüft, dass eine Dreißigjährige zugelassen wird und ein Zehnjähriger nicht. Er besteht.
Jetzt ändere ein einziges Zeichen in der Regel:
// die Regel
const mayHoldAnAccount = (age: number) => age >= 16;
// dieselbe Regel, absichtlich kaputt
const mayHoldAnAccount = (age: number) => age > 16;Wer sechzehn ist, wird jetzt abgewiesen. Merkt der Test das? Nein. Dreißig kommt weiter rein, zehn bleibt draußen, und die Suite bleibt grün. Die Regel ist falsch, und nichts hat es uns gesagt.
Mutationstests, einfach erklärt
Dieser kleine, absichtliche Fehler heißt Mutant. Mutationstests bedeuten, viele davon zu erzeugen, einen nach dem anderen, und die Tests gegen jeden laufen zu lassen:
- Ändere eine Kleinigkeit im Code: dreh einen Vergleich um, lass eine Prüfung weg, tausch einen Wert.
- Lass die Tests laufen.
- Scheitert ein Test, ist der Mutant gefangen. Gut.
- Bestehen alle Tests weiter, hat der Mutant überlebt, und ein Test fehlt. Wir schreiben ihn.
Für das Beispiel reicht ein weiterer Test: Wer sechzehn ist, wird zugelassen. Mit diesem Test färbt die kaputte Regel die Suite sofort rot.
Wie wir das nutzen
Die Reihenfolge ist wichtig. Ein Test, den wir nie scheitern gesehen haben, prüft vielleicht gar nichts. Ihn zuerst rot zu sehen, beweist, dass er den Fehler fangen würde, für den er geschrieben wurde.
Mutanten sind nicht die einzige Prüfung. Jede Änderung durchläuft auch die komplette Testsuite. Manchen Code füttern wir mit großen Mengen zufälliger Eingaben, um Fälle zu finden, an die niemand gedacht hat. Ein Prüfserver lässt die Suites, einen Teil der Mutanten und Suchen nach versehentlich veröffentlichten Geheimnissen nach Plan erneut laufen und meldet, was er findet. Am Ende jeder Phase versuchen Prüfer mit Nachdruck, das Gebaute zu knacken, bevor wir es fertig nennen.
Was es nicht beweist
Mutationstests sagen dir, dass deine Tests die Fehler bemerken würden, die du eingebaut hast. Sie können nicht beweisen, dass der Code gar keine Fehler hat, und sie ersetzen kein unabhängiges Audit. Deshalb kann auf dem Tracker nichts als fertig erscheinen, was auf ein Audit wartet, egal wie viele Tests es besteht.
Warum dich das angeht
Wenn sich ein Arbeitspaket auf unserem Tracker bewegt, dann weil sich ein Repository geändert hat, und diese Änderung ist vorher durch diese Prüfungen gegangen. Niemand kann eine Zahl eintippen. Wir zeigen dir lieber einen langsameren Balken, der stimmt, als einen schnelleren, der nicht stimmt.