Das mit dem Testen ist eine merkwürdige Sache. Meine Beobachtungen zu dem Thema sehen in Etwa folgendermaßen aus:
- Testen die ungeliebte Tätigkeit. Häufig ist das Testen eine ungeliebte Tätigkeit. Sie wird als langweilig, eintönig und unproduktiv empfunden. Viele schreiben lieber Produktivcode als Testcode. Als ich in der Uni das Softwareentwicklungsprojekt betreut hatte, musst ich meine Studenten fast schon dazu zwingen, JUnit-tests zu schreiben (und das war explizit Teil der Aufgabenstellung). Die besten Gruppen hatten eine gefühlte Testabdeckung knapp über „kaum nennenswert“.
- Testen an der Uni. An der Uni wird auch das Testen thematisiert. Aber wie… Was lernt man da? Hauptsächlich Begriffe. Blackbox, Whitebox, Testtreiber, Dummy, Unittests, Integrationstest, … Man lernt einzelne Details über Testabdeckung, Path Coverage, Statement Coverage, Branch Coverade, MCDC Coverage, … Man lernt was über statistische Testverfahren, Äquivalenzklassen und Grenzwertanalyse. Was aber lernt man nicht? Testen. Aber Zeug wie Mocking-Frameworks und TDD wurden gar nicht behandelt. Und was schon gar nicht Teil des Studium war, ist explizit mal zu lernen, wie man Code testbar macht. Testen muss man lernen wie ein Handwerk. Und wenn man mal ein gewissen Gefühl dafür bekommen hat, verliert es auch ganz schnell seinen Schrecken. Denn Testen ist eigentlich alles andere als langweilig und unproduktiv.
- Testen als Spezialqualifikation. Es gibt die einen Tests, die man selbst schreibt. Manchmal hat man aber auch den Luxus separate Tester zu haben. Das sind Leute, die die abartigsten Fehlerfälle finden und ein Gespür dafür haben, was noch alles schiefgehen könnte. Wenn man so jemanden hat, ist das ein echter Mehrwert. Automatisierte Unit-Tests sind zwar immer noch unersetzbar, aber durchaus sinnvoll ergänzbar.
- Testen und Dokumentation. Wasserfall-Tester müssen Berge von Doku schreiben. Das ist auch das, was man so in der Uni gelehrt bekommt. Testkonzepte, Statusreports, Testspezifikationen, Testergebnisse… Alles wird dokumentiert. Das passt schön in die Wasserfall-Denkweise und mag in Fällen, in denen es um sicherheitskritische Software (Autos, Flugzeuge, Computertomographen, …) geht, aus rechtlichen Gründen angebracht sein. Allerdings frag ich mich manchmal: Welchen zusätzlichen Mehrwert könnten unsere Tester liefern, wenn sie nicht die Hälfte ihrer Zeit mit Papierkram verplempern würden?
- Tests haben. Einer meiner Profs stellte immer den wissenschaftlich nachgewiesenen Effektivitätsvorteil von Inspektionen gegenüber Tests heraus. Was aber meist untern Tisch fällt, ist die Feststellung, dass das Punkt bei automatisierten Tests ein ganz anderer ist. Es kommt nicht darauf an, Tests zu schreiben. Das Tolle ist, sie zu haben. Wenn man sie einmal geschrieben hat, kann man sie regelmäßig fast ohne Aufwand neu ausführen. Und das ist wirklich ein *riesiger* Vorteil. Man kann so viel entspannter refactorn. Bestehende Funktionalität geht nicht so einfach kaputt, weil man Tests hat, die das prüfen. Nötige Verbesserungen werden nicht aus Angst, etwas kaputt zu machen, verschlafen… Viele Effekte, die ungemein positiv für die Qualität sind.
- Testen als Handwerk. Wie gesagt: Testen ist ein Handwerk, das man erlernen muss. Eines, das man in der Uni nicht lernt. Auch, wenn ich schon seit über zwölf Jahren programmiere, richtig testen hab ich erst in den letzten Monaten gelernt. Und ich hab das Gefühl, dass ich noch mehr zu lernen habe und noch mehr lernen werde.
Letztens hab ich zwei Artikel gelesen, die meinem Verständnis für Tests wieder einen Schub nach vorne verpasst haben. Und das sind die beiden:
Da steht viel Interessantes drin, aber ich will mal eines hervorheben, was ich besonders wichtig finde: Einer der Fehler bzw. ein Missverständnis, dem auch ich aufgesessen bin, ist dass es zu jeder Klasse eine Test-Klasse geben müsse. Ich hab sogar mal nen Test geschrieben, der geprüft hat, ob zu jeder Klasse ne Testklasse und zu jeder Methode ne Testmethode existiert. Und das ist Blödsinn. Der Effekt der dann auftritt, ist, dass jegliches Refactoring ein analoges Refactoring der Tests nach sich zieht. Benenne ich eine Methode um, muss ich auch alle zugehörigen Testmethoden umbenennen. Teile ich eine Klasse, muss ich auch den eine neue Testklasse schreiben, etc. Das ist ein Hemmschuh, der eigentlich nicht da sein sollte. Vielmehr sollten Tests orthogonal zum Produktivcode sein. Tests sollten sich an der Fachlichkeit orientieren, nicht an der technischen Struktur des realisierenden Codes. Es gibt also quasi pro fachlicher Anforderung eine Testklasse.
Ich hab das mal bei meinem ArgumentsParser ausprobiert und das ist tatsächlich ein enormer Fortschritt.