Flaky Tests

Ein "flaky" Test ist ein Test, der intermittierende oder sporadische Fehler aufweist und ein nicht-deterministisches Verhalten zu haben scheint. Manchmal besteht er, manchmal schlägt er fehl, und es ist unklar, warum. Diese Seite behandelt Pytest-Funktionen, die dabei helfen können, sowie andere allgemeine Strategien zur Identifizierung, Behebung oder Minderung solcher Probleme.

Warum flaky Tests ein Problem sind

Flaky Tests sind besonders problematisch, wenn ein Continuous Integration (CI)-Server verwendet wird, so dass alle Tests erfolgreich sein müssen, bevor eine neue Codeänderung zusammengeführt werden kann. Wenn das Testergebnis kein zuverlässiges Signal ist – dass ein Testfehler bedeutet, dass die Codeänderung den Test kaputt gemacht hat –, können Entwickler dem Testergebnis misstrauen, was dazu führen kann, dass echte Fehler übersehen werden. Es ist auch eine Quelle verschwendeter Zeit, da Entwickler Testsuiten erneut ausführen und irreführende Fehler untersuchen müssen.

Mögliche Ursachen

Systemzustand

Im Allgemeinen deutet ein flaky Test darauf hin, dass der Test von einem Systemzustand abhängt, der nicht angemessen kontrolliert wird – die Testumgebung ist nicht ausreichend isoliert. Tests auf höherer Ebene sind wahrscheinlicher flaky, da sie von mehr Zustand abhängen.

Flaky Tests treten manchmal auf, wenn eine Testsuite parallel ausgeführt wird (z. B. mit pytest-xdist). Dies kann darauf hindeuten, dass ein Test von der Testreihenfolge abhängt.

  • Vielleicht versäumt es ein anderer Test, hinterlassene Daten zu bereinigen, was dazu führt, dass der flaky Test fehlschlägt.

  • Der flaky Test hängt von Daten aus einem vorherigen Test ab, der nicht ordnungsgemäß bereinigt wird, und in parallelen Ausführungen ist dieser vorherige Test nicht immer vorhanden.

  • Tests, die globale Zustände ändern, können typischerweise nicht parallel ausgeführt werden.

Zu strenge Assertions

Zu strenge Assertions können Probleme mit Gleitkommavergleichen sowie Timing-Probleme verursachen. pytest.approx() ist hier nützlich.

Thread-Sicherheit

pytest ist Single-Threaded und führt seine Tests immer im selben Thread sequenziell aus, ohne selbst Threads zu erzeugen.

Selbst im Falle von Plugins, die Tests parallel ausführen, wie z. B. pytest-xdist, werden normalerweise mehrere *Prozesse* erzeugt und Tests in Batches ausgeführt, ohne mehrere Threads zu verwenden.

Es ist natürlich möglich (und üblich), dass Tests und Fixtures selbst Threads als Teil ihres Testworkflows erzeugen (z. B. eine Fixture, die einen Server-Thread im Hintergrund startet, oder ein Test, der Produktionscode ausführt, der Threads erzeugt), aber hierbei ist Vorsicht geboten.

  • Stellen Sie sicher, dass Sie auf alle erzeugten Threads warten – zum Beispiel am Ende eines Tests oder während des Teardowns einer Fixture.

  • Vermeiden Sie die Verwendung von Pytest-Primitiven (pytest.warns(), pytest.raises() usw.) aus mehreren Threads, da diese nicht thread-sicher sind.

Wenn Ihre Testsuite Threads verwendet und Sie flaky Testergebnisse sehen, schließen Sie die Möglichkeit nicht aus, dass der Test implizit globale Zustände in pytest selbst verwendet.

Andere allgemeine Strategien

Testsuiten aufteilen

Es ist üblich, eine einzelne Testsuite in zwei aufzuteilen, z. B. Unit- vs. Integrationstests, und nur die Unit-Testsuite als CI-Gate zu verwenden. Dies hilft auch, die Build-Zeiten überschaubar zu halten, da Tests auf hoher Ebene tendenziell langsamer sind. Dies bedeutet jedoch, dass Code, der den Build bricht, zusammengeführt werden kann, so dass zusätzliche Wachsamkeit bei der Überwachung der Integrations-Testergebnisse erforderlich ist.

Video/Screenshot bei Fehler

Für UI-Tests sind diese wichtig, um zu verstehen, wie der Zustand der Benutzeroberfläche war, als der Test fehlgeschlagen ist. Pytest-Splinter kann mit Plugins wie pytest-bdd verwendet werden und bei Testfehlern einen Screenshot speichern, was helfen kann, die Ursache zu isolieren.

Test löschen oder neu schreiben

Wenn die Funktionalität durch andere Tests abgedeckt ist, kann der Test vielleicht entfernt werden. Wenn nicht, kann er vielleicht auf einer niedrigeren Ebene neu geschrieben werden, was die Flakiness entfernt oder seine Quelle deutlicher macht.

Quarantäne

Mark Lapierre diskutiert die Vor- und Nachteile von Quarantäne-Tests in einem Beitrag von 2018.

CI-Tools, die bei Fehlern neu starten

Azure Pipelines (das Azure Cloud CI/CD-Tool, früher Visual Studio Team Services oder VSTS) verfügt über eine Funktion zur Identifizierung von flaky Tests und zum erneuten Ausführen fehlgeschlagener Tests.

Forschung

Dies ist eine begrenzte Liste, bitte reichen Sie ein Issue oder Pull Request ein, um sie zu erweitern!

  • Gao, Zebao, Yalan Liang, Myra B. Cohen, Atif M. Memon und Zhen Wang. „Making system user interactive tests repeatable: When and what should we control?“ In Software Engineering (ICSE), 2015 IEEE/ACM 37th IEEE International Conference on, Bd. 1, S. 55-65. IEEE, 2015. PDF

  • Palomba, Fabio und Andy Zaidman. „Does refactoring of test smells induce fixing flaky tests?“ In Software Maintenance and Evolution (ICSME), 2017 IEEE International Conference on, S. 1-12. IEEE, 2017. PDF in Google Drive

  • Bell, Jonathan, Owolabi Legunsen, Michael Hilton, Lamyaa Eloussi, Tifany Yung und Darko Marinov. „DeFlaker: Automatically detecting flaky tests.“ In Proceedings of the 2018 International Conference on Software Engineering. 2018. PDF

  • Dutta, Saikat und Shi, August und Choudhary, Rutvik und Zhang, Zhekun und Jain, Aryaman und Misailovic, Sasa. „Detecting flaky tests in probabilistic and machine learning applications.“ In Proceedings of the 29th ACM SIGSOFT International Symposium on Software Testing and Analysis (ISSTA), S. 211-224. ACM, 2020. PDF

  • Habchi, Sarra und Haben, Guillaume und Sohn, Jeongju und Franci, Adriano und Papadakis, Mike und Cordy, Maxime und Le Traon, Yves. „What Made This Test Flake? Pinpointing Classes Responsible for Test Flakiness.“ In Proceedings of the 38th IEEE International Conference on Software Maintenance and Evolution (ICSME), IEEE, 2022. PDF

  • Lamprou, Sokrates. „Non-deterministic tests and where to find them: Empirically investigating the relationship between flaky tests and test smells by examining test order dependency.“ Bachelorarbeit, Department of Computer and Information Science, Linköping University, 2022. LIU-IDA/LITH-EX-G–19/056–SE. PDF

  • Leinen, Fabian und Elsner, Daniel und Pretschner, Alexander und Stahlbauer, Andreas und Sailer, Michael und Jürgens, Elmar. „Cost of Flaky Tests in Continuous Integration: An Industrial Case Study.“ Technische Universität München und CQSE GmbH, München, Deutschland, 2023. PDF

Ressourcen