Unit-Tests in Data-Science-Projekten

Als eines der jüngsten Gebiete der IT befindet sich Data Science in vielen Unternehmen noch in der Findungs-/Beweisphase, wodurch bei den ersten Projekten wenig Wert auf Infrastruktur oder CI/CD (Continuous Integration/Continuous Delivery) -Mechanismen gelegt wird. Sobald jedoch der Mehrwert von Data Science im eigenen Unternehmen erkannt wird und stetig gesteigert werden möchte, kommt man um Fragestellungen wie Deployment und Scalability nicht herum. Dazu gehören neben Datenpipelines und Versionierungstools wie Git auch Integrations- und Unit-Tests. Dieser Blogpost gibt einen kurzen Überblick zum Thema Unit-Tests und den 5 W’s, um erfolgreich mit Unit-Tests zu starten.
Warum brauchen wir Unit-Tests (in Data-Science-Projekten)?
In der Softwareentwicklung gehören Unit-Tests bereits zum Daily-Business von Entwicklern. Wird eine neue Funktion/Methode (Unit) installiert, werden auch direkt Unit-Tests implementiert, um die Funktionalität unabhängig von anderen Systemen zu testen und zu gewährleisten. Weitere Vorteile von Unit-Tests sind, dass Edgecases einfach getestet werden können und somit das gesamte System robuster wird. Durch „Mocking“ von Funktionen können komplexe Abhängigkeiten zu Datenbanken, Clouddiensten und zeitintensive Funktionen schnell auf ihre Funktionalität getestet werden. Somit erhält man in wenigen Sekunden einen guten Überblick über die Zuverlässigkeit der einzelnen Komponenten des Softwaresystems. Ein Nachteil ist lediglich der Mehraufwand. Sowohl initial als auch über die Systemlebenszeit benötigt man Ressourcen um die Tests zu implementieren als auch um Anpassungen der Tests bei Codeänderungen und Erweiterungen vorzunehmen. Dementsprechend sind Unit-Tests spätestens ab dem Level der Produktivität des Systems sinnvoll und sollten eingesetzt werden.
Wie werden die Tests umgesetzt?
Unit-Tests werden in der Programmiersprache umgesetzt, in der auch die Funktionen/Methoden implementiert wurden. Für Python bietet sich das Package „pytest“ mit seinen Erweiterungen an. Dieses bietet einige Quality of Life Verbesserungen im Vergleich zu anderen Packages wie z.B. „unittest“. Sinnvolle Unterstützung bieten auch die Verwendung von makefiles, womit man oft verwendete Konsolenbefehle abkürzen kann. Mit Code-Coverage (Package: pytest-cov) erhält man einen Überblick, wie viel der Codebase bereits durch Unit-Tests abgedeckt ist. Befindet man sich in Cloudumgebungen, können und sollten die Unit-Tests auch in Pipelines integriert werden (z.B. in DevOps).
Wann sollen wir damit anfangen?
Sobald das Data-Science-System den Mehrwert bewiesen hat, und das System produktiv gesetzt wird. Ab diesem Zeitpunkt ist jede Hilfe, welche die Robustheit des Systems verbessert, willkommen. Da Unit-Tests direkt von den Entwicklern implementiert werden können und sollen, braucht man für diese Art von Tests nicht notwendigerweise Software-Tester. Software-Tester werden dann für umfangreichere Systemtests (Integration-Tests) benötigt, wo sowohl Data-Science-Komponenten, als auch Backend, Frontend und UI/UX und deren Zusammenspiel getestet werden.
Wo sollen wir anfangen?
Am besten wird dort gestartet, wo Unit-Tests bereits am verbreitetsten sind: Bei reiner Softwareprogrammierung. Jedes Data-Science-Projekt hat neben Datenverarbeitung, der Entwicklung von Algorithmen und dem Trainieren von Modellen auch kleine Teile reiner Softwareentwicklung in sich. Das sind Dinge wie das Abspeichern von Ergebnissen und Daten, Herunterladen von Konfigurationsdateien, Transformationen von Datentypen, Verbindungsaufbau zu anderen Systemen (z.B. Datenbanken, Azure) etc. Hier kann man sehr schön direkt auf die Ergebnisse testen und bekommt ein Gefühl, wozu Unit-Tests da sind und wie diese aufzubauen sind. Bei Data-Science-Komponenten sollte eher die Struktur der Ergebnisse getestet werden, als die Ergebnisse selbst, da Ergebnisse für mehrere Trainingsdurchläufe unterschiedlich sein können, die Struktur jedoch unverändert bleibt.
Welchen Mehrwert liefern uns Unit-Tests in Data-Science-Projekten?
Unit-Tests führen dazu, dass die Software schon während der Entwicklung getestet werden kann, und somit die Verlässlichkeit des Codes gesteigert wird. Dies führt zu weniger Fehlern und kostet weniger Zeit, die in Debugging und Bugfixes fließen muss. Das gesamte System wird dadurch stabiler, und auch die Entwicklung von weiteren Features geht schneller. Unit-Tests geben mehr Sicherheit und es müssen weniger händische Tests durchgeführt werden. Somit verwandelt sich der Mehraufwand durch die Implementierung der Tests schnell in echten Mehrwert. Diesen wissen auch die Entwickler zu schätzen.
Fazit
Unit-Tests in Data-Science-Projekten sind noch wenig verbreitet. Sie liefern jedoch ab dem Zeitpunkt der Produktivität des Produkts einen nicht zu unterschätzenden Mehrwert für die Robustheit des Produkts und die Effizienz der Programmierung.