Test-Driven Development

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Dienstag 9. Oktober 2007, 23:06

Edit (Leonidas): Vom Thread "Klasse mit statischen Attributen ?" abgetrennt.
Goswin hat geschrieben:Blackjack: Ich programmiere nicht deshalb in Python, weil Python perfekt ist oder ich es dafür halte. Ich kenne keine perfekte Programmiersprache, und mit einer Haltung wie du sie mir empfiehlst, könnte ich überhaupt nicht programmieren. Natürlich kann z.B. Java besser kapseln, aber dafür hat Java eben andere Nachteile. Nur, die Nachteile von Python wird man als Pythonprogrammierer doch wohl beim Namen nennen dürfen, und auch die beste Methode suchen dürfen, damit zu leben!
Ich kann mich dem, was Blackjack gesagt hat, nur anschließen. Python verfolgt die Philosophie "Der Programmierer weiss am besten, was er tut" sowie der Philosophie von Unittests: "Ungetesteter Code ist kaputter Code".
"Statische" Sprachen schränken den Programmierer ein, um eine Art von Fehlern zu verhindern. Viele (Logik-)Fehler hingegen können nicht erkannt werden. Für diese braucht man Unittests. Unittests erkennen aber die Art von Fehlern, die der Compiler erkennen kann. gleich mit. Warum also sollte der Compiler überhaupt die Prüfungen durchführen?

Um mal dein Beispiel aufzugreifen, sagen wir es gäbe eine Möglichkeit, "random.seed = 1" zu unterbinden. Dann wäre es doch nur logisch, den Fall abzufangen, dass man "a = foo" schreibt, obwohl man "a = foo()" meinte.

Damit verliert man aber auch die Möglichkeit, Funktionen zu übergeben oder muss dafür eine andere, explizitere Syntax einführen.

Das Problem mit einer "strengen" Sprache ist, dass der Compiler ein paar(!) Fehler erkennt und anmeckert, aber bei weitem nicht alle.

Und dadurch gewinnst du nichts: du musst trotzdem noch einen Unittest schreiben, um die Funktionalität zu testen. Viel schlimmer noch: die (teilweise) Überprüfung durch den Compiler gibt dir ein Gefühl von falscher Sicherheit, dass dich dazu verleiten kann, eben "diesesmal doch keinen Testcase zu schreiben", weil die Funktionalität ja so trivial ist.

In Python hingegen finde ich es ganz praktisch, dass du ein etwas mulmiges Gefühl hast, wenn du Code ohne entsprechenden Unittest schreibst. "Ungetesteter Code ist kaputter Code" ist hier viel offensichtlicher.

Jeder Programmierer hat eine eigene Programmierphilosophie, und wenn deine ist, dass es besser ist, wenn der Compiler dir ein bisschen auf die Finger schaut, dann gibt es genug Sprachen, die diese Philosophie teilen und du mit diesen besser aufgehoben bist! Dass soll nicht heißen, dass Python besser oder schlechter als andere Sprachen ist, sondern nur, dass die Philosophie eine andere ist.

Du bist am produktivsten, wenn du nicht "gegen die Sprache kämpfen" musst, weil sie die Dinge anders sieht als du. Ich z. B. habe dieses Problem bei Sprachen wie C++ und Java, eben weil ich deren Philosophie nicht ganz teile und programmieren in Python fühlt sich für mich eben natürlicher an. Wenn dass bei dir nicht der Fall ist, ist Python für dich wohl nicht die richtige/beste Wahl.

Ich denke dass ist, was Blackjack sagen wollte. (Er kann mich natürlich gerne korrigieren)

Edit (Leonidas): Vom Thread "Klasse mit statischen Attributen ?" abgetrennt.
poker
User
Beiträge: 146
Registriert: Donnerstag 20. September 2007, 21:44

Dienstag 9. Oktober 2007, 23:32

Goswin hat geschrieben: Un da ich die Zufallszahlen nicht sofort überprüft habe, merke ich ziemlich viel später, dass meine Rechnungen nun nicht reproduzierbar sind. Dies ist nur eins von vielen Beispielen wo es besser wäre, alle Attribute einer Klasse von vornherein festzuschreiben.
Nein! Pass gefälligst auf oder nutze Code Vervollständigung! IMO ist das, was du bemängelst, eines der wichtigsten Merkmale dynamischer Sprachen bzw. sie machen sie erst zu solchen!
BlackJack hat geschrieben:Wenn Du das so siehst, solltest Du nicht in Python programmieren.
Sehe ich auch so.
Goswin hat geschrieben:mit einer Haltung wie du sie mir empfiehlst, könnte ich überhaupt nicht programmieren[/b].
Ja, und? Was erwartest du? Du nutzt eine dynamische Sprache und beschwerst dich über Merkmale die sie gerade zu dem macht? Das ist so wie wenn ich Haskell programmiere und sage "Muss dieser ganze funktionalen scheiß sein? Geht es nicht auch OO und Imperativer?".
Goswin hat geschrieben:Natürlich kann z.B. Java besser kapseln, aber dafür hat Java eben andere Nachteile. Nur, die Nachteile von Python wird man als Pythonprogrammierer doch wohl beim Namen nennen dürfen, und auch die beste Methode suchen dürfen, damit zu leben!
Wie gesagt, das was du als Nachteil beschreibst in eines der vorteile von Python und anderen dynamischen Sprachen wie z.B. Ruby. Und Ruby ist da sogar weit aus heftiger da du da sogar Builtin-Classes änder kannst und viel mehr scheiße anrichten kannst :). Muss man halt aufpassen was man macht.
Sprich: Das denken muss immer noch der Programmierer übernehmen (und soll es auch) und gefälligst aufpassen was er macht!

Das ist meine Meinung und dazu stehe ich, auch wenn es hart rüberkommt.

Außerdem sind Joghurts Ausführungen absolut in jedem Punkt richtig!

Auch das was alle hier über Unittest (Coverage nicht vergessen) gesagt wurde, ist für dynamischen Sprachen um so wichtiger und ist unabhängig davon sowieso für **jedes** ernsthaftes Projekt angebracht! Ich gehe sogar soweit - wie es Joghurts ganz dezent angedeutet hat - das ich jeden Code ohne Unittest als potenziellen kaputten Code ansehe (Trivial code ausgenommen)! Und was ich von Code ohne Coverage halte kann man sich ja denken ;) Irgendwo toter Code vorhanden ...
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Mittwoch 10. Oktober 2007, 14:34

@poker: Coverage hatte ich bisher noch nie gehört. Nach ein bisschen Googlen weiß ich jetzt aber wohl, worum es dabei geht. Für Python habe ich dazu coverage.py gefunden. Arbeitest Du damit? Was verwendest Du ansonsten? Wie machst Du das dann vom Programmierablauf her?
MfG
HWK
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Mittwoch 10. Oktober 2007, 15:26

Ned Batchelders `coverage.py` wird meines Wissens in einem der Pocoo-Projekte, ich meine (u.a.) in Pygments, verwendet. Schau doch mal in die Repositories für ein Beispiel, wie es eingebunden werden kann.
Benutzeravatar
birkenfeld
Python-Forum Veteran
Beiträge: 1603
Registriert: Montag 20. März 2006, 15:29
Wohnort: Die aufstrebende Universitätsstadt bei München

Mittwoch 10. Oktober 2007, 17:04

Siehe die "coverage"-Einstellung unter http://dev.pocoo.org/hg/pygments-main/f ... sts/run.py.
Dann lieber noch Vim 7 als Windows 7.

http://pythonic.pocoo.org/
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Mittwoch 10. Oktober 2007, 17:17

Danke! Coverage.py und das "Pocoo-Testfile" werde ich mir mal genauer anschauen.
MfG
HWK
poker
User
Beiträge: 146
Registriert: Donnerstag 20. September 2007, 21:44

Mittwoch 10. Oktober 2007, 19:50

HWK hat geschrieben:@poker: Coverage hatte ich bisher noch nie gehört. Nach ein bisschen Googlen weiß ich jetzt aber wohl, worum es dabei geht. Für Python habe ich dazu coverage.py gefunden. Arbeitest Du damit? Was verwendest Du ansonsten? Wie machst Du das dann vom Programmierablauf her?
MfG
HWK
Hi.

Ich nutze figleaf das auf Ned Batchelder coverage.py basiert. Es entspricht zum größten teil Ned Batchelder Implementierung und wurde nur ein wenig aufgebohrt (reporting, etc). Bevor ich figleaf kannte habe ich ``coverage.py`` genutzt.

Zu der Frage was ich sonst noch nutze: Für die Unit tests finde ich IMO py-test am besten.

Für teile die man schlecht Unit testen kann nutze ich Mock-Objekt: http://python-mock.sourceforge.net/
Das ist aber bisher so gut wie garnicht bei mir vorgekommen.


Für alle die den Thread entdecken und nicht wissen wozu man sowas Braucht:
Die Notwendigkeit von einem Abdeckungstest (Coverage) liegt ja darin begründet um "toten Code" (Nicht vom Unit test getestet) zu identifizieren um dann dafür einen Unit test zu implementieren bzw. zu erweitern. Sprich, erst ein Anschließender Coverage gewährleistet das die Unit tests auch vollständig sind und machen daher das schreiben von vollständigen Unit tests erst möglich!

Für gewöhnlich läuft das in Python so, das man Unit tests schreibt und alle beteiligten zu testenden Komponenten importiert. Nach Fertigstellungen und starten der Unit test erfolgt danach ein start des full Coverage test. Durch den vom Coverage test erzeugten Report kann man dann die Bereiche sehen die nicht ausgeführt wurden.

Beispiel: Nähmen wir folgenden Triviale Funktion:

Code: Alles auswählen

class FoobarError(Exception): pass

def foobar(para):
    if not isinstance(para, basestring):
        raise ValueError()
    ...
    if ...
    elif ...
    else:
        raise FoobarError()
Wenn wir jetzt ein Unit test für foobar schreiben und den Unit test starten mit anschließenden Coverage, macht Coverage folgendes: Coverage Untersucht ob der Unit test die Funktion ``foobar`` in allen möglichen Varianten aufgerufen hat, so das alle möglichen Verzweigungen von ``foobar`` einmal aufgeruffen wurden. Wenn dabei rauskommt das einige Verzweigungen nicht aufgeruffen wurden (in diesem Beispiel das offensichtlichste der isinstance test, das einige wohl nicht testen werden), taucht das in dem von Coverage erzeugten Report auf, mit den Code stellen.

Dieses Verfahren des implementieren von Unit test und das spätere pflegen dieser, nimmt einen Entwickler sehr viel arbeit ab und gehört IMO für mich zum guten Ton :)

Für die, die sich mit der Thematik ein wenig mehr beschäftigen wollen, sein diese Seite empfohlen, die kompakt das Thema erklärt.

edit:Alle die Wissen wohlen wie man für GUI Anwendungen Unit testet schreibt, sei diese Seite empfohlen. Ist zwar auf wxPython bezogen, lässt sich aber auch für andere benutzen, da dort nur allgemein beschrieben wird wie man vorgehen kann.
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Mittwoch 10. Oktober 2007, 23:19

poker hat geschrieben:Zu der Frage was ich sonst noch nutze: Für die Unit tests finde ich IMO py-test am besten.
Ich möchte auch noch nose in die Runde werfen
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Donnerstag 11. Oktober 2007, 11:53

Ein paar (meinetwegen auch reallife-)Beispiele zum Testen von Datenbank- und Socket-Zugriffen würden mich brennend interessieren. Ich habe mir zwar die zahlreichen Python-Mock-Implementierungen sowie Ressourcen wie z.B. Googles Testing-Blog angesehen, aber so *richtig* komme ich da auf keinen grünen Zweig.

Achso, `py.test` nutze ich ebenfalls, da ich sehr schätze, dass es keine Vererbung voraussetzt und hübsch selbst alle Testmodule und -Callables findet. In irgendeinem Blog wurde es mit `unittest` und `nose` verglichen und `unittest` kam am besten weg - da kommt es allerdings immer auf die Anforderungen an, und mir ist letzteres einfach zu umständlich. Wenn einen das Framework schon vom Schreiben von Tests abhält, its das schon mal schlecht, gerade beim Einstieg in die Materie.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Donnerstag 11. Oktober 2007, 16:54

@poker: Bedeutet das, dass durch Unittests jede Zeile des Programmcodes mindestens einmal ausgeführt werden soll? Ist das nicht ein bisschen aufwendig und in vielen Fällen auch unnötig?
BlackJack

Donnerstag 11. Oktober 2007, 17:05

Genau in den Zeilen wo Du denkst es wäre unnötig, verstecken sich am Ende die Fehler. ;-)

Die Zeilen, die bei normaler Benutzung des Codes ausgeführt werden, lassen sich auch leicht von Unittests abdecken, das passiert ja nahezu automatisch. Die anderen, eher besonderen Fälle sollte man dann aber auch testen. Habe zum Beispiel schon öfter Quelltext gesehen wo irgendwelche Fehlerbedingungen abgeprüft wurden, und diese Prüfungen fehlerhaft waren. Hat bloss nie jemand gemerkt weil die entsprechende Fehlersituation in der Praxis nicht aufgetaucht ist. Oder vielleicht doch, und es hat wegen der fehlerhaften Prüfung nur keiner gemerkt.
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Donnerstag 11. Oktober 2007, 17:08

HWK hat geschrieben:Bedeutet das, dass durch Unittests jede Zeile des Programmcodes mindestens einmal ausgeführt werden soll?
Ja. Und das natürlich auch mit sinnvollen Testwerten.
HWK hat geschrieben:Ist das nicht ein bisschen aufwendig und in vielen Fällen auch unnötig?
Wenn deine Anwendung ihre Arbeit korrekt (so korrekt wie es eben menschenmöglich ist :-) ) machen soll bleibt dir nichts anderes übrig. Spätestens wenn du größere Änderungen machen musst, was ja immer mal wieder vorkommt, bewährt sich der zusätzliche Aufwand.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Donnerstag 11. Oktober 2007, 17:16

Schluck! Und das als Hobby-Programmierer. Dann muss man sich wohl vorher gut überlegen, bei welchen seiner kleinen oder großen selbstprogrammierten Helferlein dieser Aufwand gerechtfertigt ist.

Ich versuche gerade, mich weitergehend über das Testen zu informieren. Im Python-Manual wird unter 5.4.1 Writing Unit Tests for the test package auf das Buch Test Driven Development von Kent Beck verwiesen. Lohnt sich das?
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Donnerstag 11. Oktober 2007, 20:29

HWK hat geschrieben:Bedeutet das, dass durch Unittests jede Zeile des Programmcodes mindestens einmal ausgeführt werden soll? Ist das nicht ein bisschen aufwendig und in vielen Fällen auch unnötig?
"Ungetester Code ist falscher Code" -> "Ungetestete Zeilen sind falsche Zeilen"

Der Vorteil von Unittests macht sich dann bemerkbar, wenn du Refaktorisiert; sobald die Tests durchlaufen, kannst du ziemlich sicher sein, dass sich das Programm so verhält wiei vorher (wenn nicht, waren deine Unittests nicht ausreichend)

Übrigens sollte man Unittests immer erweitern; jeden Bug den man findet, sollte man in einen Unittest packen und dann den Bug fixen. Sobald der Test durchläuft, ist der Bug gefixt und man kann sicher sein, dass er nicht nochmal auftritt.
Joghurt
User
Beiträge: 877
Registriert: Dienstag 15. Februar 2005, 15:07

Donnerstag 11. Oktober 2007, 20:36

HWK hat geschrieben:Schluck! Und das als Hobby-Programmierer. Dann muss man sich wohl vorher gut überlegen, bei welchen seiner kleinen oder großen selbstprogrammierten Helferlein dieser Aufwand gerechtfertigt ist.
Unittests sind dazu da, dir das Programmiererleben zu erleichtern. Sobald du ein Programm hast, was du oder andere später warten müssen, lohnen sie sich. Für einen kleinen Hack, der kurz eine Arbeit machen soll und danach weggeschmissen wird, macht es dementsprechend keinen Sinn, Unittests zu schreiben, weil du insgesamt mehr Zeit brauchst, um das Programm während seiner ganzen Lebensdauer (die sehr kurz ist) zu warten/am laufen zu halten.


Wenn du dir hingegen ein kleines Tool schreibst, dass meinetwegen bestimmte Dateien sichert, macht es Sinn, Tests zu haben, da du das Programm u.U. später mal erweitern wirst und du spätestens dann eh Test schreiben solltest.
Antworten