Pi Tastic, PIT, Java, Test
  • Software-Modernisierung

{Pi-Tastic Tests - Mutation Tests in der realen Welt}

Sind unsere Tests wirklich gut genug? Kann Mutation Testing die Antwort liefern?

Ein Erfahrungsbericht, wie wir das Framework PIT in verschiedenen Java-Projekten genutzt haben, um die Qualität von Unittests zu prüfen, Schwächen aufzudecken und wertvolle Einblicke zu gewinnen.

Was sind Mutation Tests überhaupt?

Es geht darum, die Qualität von Tests zu ermitteln. Dabei werden Fehler (oder Mutationen) automatisch in den Code eingefügt und auf diese Mutationen die Tests ausgeführt. Sollten die Tests durch die Mutation fehlschlagen, wird diese erkannt (gut), waren die Tests erfolgreich, wurde die Mutation nicht erkannt  (schlecht).

Die Qualität der Tests wird prozentual gemessen anhand der erkannten Mutationen. Wenn ein Test erfolgreich ist, obwohl im zu testenden Code Fehler eingebaut werden (z.B. Vergleichsoperatoren ausgetauscht werden), dann ist der Test im besten Fall ungenau, im schlechtesten Fall falsch. Ein weiterer Grund dafür, dass eine Mutation nicht erkannt wird, ist eine ungenügende Testabdeckung.

PIT, Java, Mutant, Tests, Pi Test

Warum PIT für Java-Projekte?

PIT ist ein Mutation Test Framework für Java. Da wir zum Großteil Java-Anwendungen bei unseren Kunden vorfinden, haben wir uns für dieses LF-Projekt für PIT entschieden. PIT zeigt nicht nur Schwächen auf, sondern hilft dabei, gezielt Lücken zu schließen und die Tests sukzessive zu verbessern. 

Warum ist das für uns interessant?

Gute Tests sind für langlebige Projekte ein essentieller Bestandteil. Gerade bei Projekten, wo man die Fachlichkeit nicht kennt, oder erst später zum Projektteam gestoßen ist, kann es schwer sein, einzuschätzen, wie gut die Testsuite ist. Zwar bieten Werkzeuge wie SonarQube genau diese Metriken an,  man muss jedoch auch bedenken, dass eine hohe Testabdeckung nicht automatisch bedeutet, dass die Tests qualitativ gut sind.

Daher ist PIT sehr hilfreich, um die Testqualität zu ermitteln. Lücken in der Testsuite werden aufgezeigt, und wir können sehen, wo es in der Testabdeckung noch Löcher gibt, die noch gefüllt werden müssen.

Unser Vorgehen

Um das Potential von PIT auszutesten, haben wir uns für ein mehrstufiges Vorgehen entschieden. Mit mehr Erfahrung sollte die Größe und Komplexität der auszuwertenden Projekte steigen.

 

Den Anfang machte unser “Advent-of-Code”-Repository, – ein kleines Miniprojekt ohne Dependencies, welches hervorragend für ein erstes Kennenlernen war.. 

Sobald klar war, wie PIT in ein Maven-Projekt erfolgreich integrierbar ist, haben wir uns an einige Open-Source-Projekte gewagt. 

Am Schluss wollten wir PIT dann auch noch in unseren Kundenprojekten verwenden, um dann im Abschluss alle Ergebnisse gegenüberzustellen. Dadurch konnten wir auch gleich direktes Feedback zu diesen Projekten erhalten und die Testsituation dort signifikant verbessern.

 

Weiters wollten wir die vorhandenen Konfigurationsmöglichkeiten erkunden. Welche Auswirkungen haben unterschiedliche Mutation Sets auf das Ergebnis? Wie wirken sich Timeouts aus? Und ganz wichtig: Wie funktioniert die History-Funktion, damit nur neuer Code getestet werden muss und nicht immer das komplette Projekt?

Unsere Erkenntnisse

Voraussetzung für das Ausführen von PIT ist, dass alle Tests fehlerfrei durchlaufen. Dies sollte unserer Meinung nach allerdings die Grundvoraussetzung für jedes Projekt sein.

 

Mehr oder weniger überraschend für uns war die Durchlaufzeit der Mutation Tests.  Diese divergiert nämlich stark zwischen den getesteten Projekten. Liegt sie bei einem eher kleinen Projekt in unseren Probeläufen bei nur ca. 7 Minuten, so kann sie bei etwas größeren Projekten schon auch auf über 3 Stunden ansteigen (apache-commons-lang3). Auffallend hierbei ist, dass es im Vorhinein schwierig ist vorherzusagen, wie lange ein Durchlauf dauern wird. Die erste Vermutung, dass Frameworks tendenziell länger in der Ausführung brauchen als Applikationen, konnte nur bedingt bestätigt werden.

Projekt Line Coverage Mutation Coverage Test Strenght
apache-commons-lang3 96% 86% 89%
apache-maven 34% 19% 58%
Kundenprojekt A 13% 11% 80%
Kundenprojekt B 21% 11% 78%
Kundenprojekt C 88% 43% 93%
Kundenprojekt D 32% 27% 91%

Für die langen Durchlaufzeiten gibt es allerdings auch Lösungsansätze:

  • Verringern der getesteten Mutationen bzw. Mutations-Modus definieren
  • “Continous PIT” – History Funktion

 

Ein Verringern der getesteten Mutationen reduziert zwar die Durchlaufzeit, allerdings wird auch das Ergebnis dadurch eingeschränkt und das Ergebnis wird dadurch evtl. weniger aussagekräftig. Daher wird es eher empfohlen, die Mutationen anhand der Applikation zu definieren, dies benötigt aber Fachwissen über die Applikation.

Bei Continuous PIT wird durch  laufendes Testen der Änderungen eines Projektes immer nur jener Code ausgewertet, der neu dazu gekommen ist oder sich geändert hat.. Dabei wird beim ersten Durchlauf eine Baseline gezogen, indem man PIT ganz normal ausführt. Ab diesem Zeitpunkt kann man dann mittels einer History-Funktion in PIT dann dazu übergehen, nur geänderten Code zu mutieren, was die Durchlaufzeiten natürlich drastisch reduziert.

Unser Fazit

Trauen wir uns nun mithilfe von PIT zu sagen, ob eine Testsuite verlässlich ist? Wie immer ist die Antwort ein eindeutiges “Jein”.

 

Es liefert eine Aussage über die Qualität der Unittests, die vorhanden sind. Eine hohe Testabdeckung in Kombination mit hoher Teststärke stimmt uns dabei stark optimistisch. Sollte das nicht der Fall sein, heißt das aber nicht, dass die Testsuite unbedingt schlecht ist. Zwei Gründe dafür sind: 

  • Eine niedrige Coverage bedeutet nicht unbedingt große Lücken im Testing – wenn die vorhandenen Tests mit sehr viel Bedacht entwickelt wurden um die Kernfunktionalität zu gewährleisten, dann kann das durchaus eine gute Testsuite sein
  • PIT funktioniert nur auf Unittests, Testsuites, die auf E2E- oder Integrationstests aufbauen, können damit nicht bzw. nur bedingt geprüft werden

 

Es wird für uns also nur eine Metrik von vielen sein, die sich – gemeinsam mit anderen – zu einem Gesamtbild über die Verlässlichkeit der Testsuite zusammenfügen.

Trotzdem (oder gerade deshalb?) hat sich PIT als sehr probates Mittel herausgestellt, um Lücken im Testing zu finden – alle an dem Projekt beteiligten Entwickler möchten es in ihre Projekte einführen, um dort die Qualität der Unittests regelmäßig zu testen und dadurch auch weiter zu verbessern

 

Und dieses wunderschöne Diagramm, erstellt von unserem Senior-Hobby-Grafiker Sascha, veranschaulicht, wie wir die PIT-Ergebnisse künftig interpretieren werden:

geschrieben von:
Andreas
WordPress Cookie Plugin von Real Cookie Banner