Warum wir Unit-Tests für Ruby-Programmme schreiben sollten

29 12 2007

Ein schönes Beispiel, wie nützlich Tests für Ruby (und auch für andere Sprachen) Programme sein können, habe ich vorgestern erlebt.

Ich habe ein Gem erstellt, welche Spreadsheet-Dateien verarbeiten kann (http://roo.rubyforge.org).

In einer Newsgroup fragte nun jemand, mit welchem Tool man am besten Excel-Dateien in CSV-Dateien umwandeln kann. Ich habe darauf geanwortet, daß das mit ‚roo‘ gehen würde. Kurz darauf kam die Antwort, daß das nicht funktionieren würde, und daß die Methode ‚to_csv‘ welche in meinem Programm eine CSV-Ausgabe entweder nach stdout oder in eine Datei schreibt, nur für Openoffice- und Google-Spreadsheets, nicht jedoch für Excel-Spreadsheets funktionieren würde.

Ich war ziemlich verblüfft, weil ich sicher war, daß ich dies auf für Excel-Dateien schon implementiert hatte und daß dies auch schon funktioniert hätte.

Ich habe das dann bei mir überprüft – und tatsächlich, bei Excel-Dateien funktionierte es nicht.

Was war passiert? Wie konnte das passieren, wo ich doch speziell für dieses Gem eigentlich alle Funktionen mit Testfällen abgedeckt hatte?

Ich muß einschieben, daß ich generell ein großer Freund von Test Driven Development bin und ich auch für dieses Programm danach vorgegangen bin, was eine große Hilfe bei allen Erweiterungen ist, weil man einfach die vorhandenen Testfälle immer wieder ablaufen lassen kann, um zu testen, ob alles noch wie gewünscht funktioniert.

Die Lösung des Problems war dann relativ simpel: Ich hatte beim ersten Entwurf meines Programms als erstes die Klasse ‚Openoffice‘ (Spreadsheets) geschrieben und später die Klasse ‚Excel‘ welche eine Kind-Klasse von Openoffice war, und deshalb auch deren Methode ‚to_csv‘ für die Ausgabe als CSV-Datei geerbt hatte. So weit, so gut.

Im Lauf der späteren Entwicklung des Programms habe ich entschieden, daß dieses Design für den Benutzer zwar funktioniert hat, im Sinn der reinen OO-Lehre aber nicht ganz korrekt war, weil ein Excel-Objekt natürlich kein Kind-Objekt einer Openoffice-Klasse ist.

Ich habe dann eine generische Klasse ‚GenericSpreadsheet‘ eingeführt, von der sowohl die Openoffice- als auch die Excel-Klasse (und später auch noch die Google-Klasse) erben.

Im OO-Sinn war dieses Design nun wesentlich besser, aber die Methode ‚to_csv‘ war nun nur in der Openoffice-Klasse und nicht in der Excel-Klasse vorhanden. Ich hatte es in Kommentaren zwar schon zum Auslagern in die allgemeine Spreadsheet-Klasse markiert, dies aber noch nicht wirklich getan.

So – die Excel-Klasse war nun ihrer ‚to_csv‘ Methode beraubt, da sie nicht mehr von Openoffice erbt.

Warum haben das die Tests nicht aufgedeckt?

Es gab zwar auch für Excel-Objekt Tests, die die CSV-Ausgabe abgedeckt haben, allerdings habe ich dieses Test nur im Rahmen von Tests für ziemlich große Spreadsheet-Dateien mit mehreren tausend Zeilen verwendet. Da diese Tests aber im Vergleich zu kleineren Spreadsheet-Testdateien relativ lange dauerten, habe ich die lange laufenden Test mit einem speziellen Schalter wahlweise abschaltbar gemacht. Dies führte dazu, daß mir dieser spezielle Fehler durch die Lappen gegangen ist, weil ich diese lang laufenden Test nicht mehr ausgeführt hatte.

Die Lösung wäre natürlich gewesen (und habe ich jetzt auch als Testfälle eingebaut), die CSV-Ausgabe nicht nur im Rahmen von großen Spreadsheets zu testen, sondern generell und auch mit kleineren Test-Spreadsheets.

Advertisements

Aktionen

Information

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s




%d Bloggern gefällt das: