Gedanken über die APIs der Python Testing Frameworks

Alles, was nicht direkt mit Python-Problemen zu tun hat. Dies ist auch der perfekte Platz für Jobangebote.
Antworten
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Nabend zusammen,

ich sinnierte gerade darüber nach, wieso die gängigen Unittesting Frameworks unter Python auf Namenskonventionen setzen und nicht auf Dekoratoren? Ist das eher historisch bedingt (Die Dekorator-Syntax gab es iirc ja erst ab Python 2.4?)? Oder steckt der Gedanke dahinter, dass man das Wort "Test" eh in einer Testfunktion benutzen sollte und sich somit überflüssiges Tippen spart?

Zur Verdeutlichung einmal als Code:

Code: Alles auswählen

# so ist der Standard
def test_foo():
    pass

# So ginge es doch auch
@test
def foo():
    pass
Weiß jemand etwas dazu zu sagen? (Oder hat eine eigene Vermutung / Meinung?)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@Hyperion: `nose` hat doch zum Beispiel `nose.tools.istest()` als Dekorator.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Hm... da muss ich mir das wohl noch mal genauer angucken.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
lunar

@Hyperion py.test nutzt zwar normalerweise Namenskonventionen zum Auffinden von Tests, allerdings lässt es sich über seine API so weit anpassen, dass ein Test-Collector basierend auf Dekoratoren relativ leicht zu implementieren ist.

JUnit hat diese Namenskonvention übrigens nur eingeführt, weil Java schlicht keine andere praktikable Möglichkeit zur Identifizierung von Testfällen bot, bevor Annotations eingeführt wurden. Die meisten Testbibliotheken, die ich kenne, verzichten auf Namenskonventionen, und nutzen entweder Metadaten wie Attribute oder Annotations zur Identifizierung von Tests, oder verlangen die explizite Registrierung von Testfällen in einer Testsuite.

Eigentlich fällt mir nur py.test als Testbibliothek ein, die auf Namenskonventionen setzt. Ich finde das nicht so toll (py.test nutze ich aus anderen Gründen), gerade bei "py.test". Die Folge sind hässliche Namen, unübersichtliche Ausgaben, da überall "test_" rumfliegt, und man den eigentlichen Testnamen erst herauspicken muss, und gelegentlich ein stillschweigend übergangener Testfall, weil man statt "test_" versehentlich "teat_" geschrieben hat...
derdon
User
Beiträge: 1316
Registriert: Freitag 24. Oktober 2008, 14:32

Wie du aber selber erkannt hast, kannst du das Verhalten von py.test sehr stark deinen Wünschen anpassen und dir deinen eigenen Testrunner schreiben, der nach völlig beliebigen Kriterien Funktionen als Tests erkennt oder aber du registrierst Tests explizit, ganz wie du es möchtest. Das mit der Namenskonvention ist also einfach nur das Defaultverhalten, mehr nicht.
lunar

@derdon Und? Habe ich irgendetwas anderes gesagt?

Du machst es Dir auch etwas zu einfach mit der Aussage, es wäre „einfach nur das Defaultverhalten.“ Das impliziert, dass man dieses Verhalten einfach schnell umstellen können. Das kann man nicht, und die Test-Discovery selbst zu implementieren, ist eben auch nur „relativ einfach“. Die py.test API ist nicht so gut dokumentiert, als dass diese Implementierung locker und schnell von der Hand gehen würde. Außerdem: Fange ich an, meine eigene Test-Discovery zu schreiben, bleibt von py.test nicht mehr so viel, und ich kann irgendwann auch einfach gleich mein eigenes Test-Rahmenwerk schreiben. ;)

Nun, ich finde die Plugin-API von py.test toll, sie ist neben funcargs der Grund, warum ich py.test gegenüber nose bevorzuge. Doch eine Test-Bibliothek sollte mir die Arbeit erleichtern, nicht mir zusätzliche bescheren. Deswegen halte ich es nicht für sinnvoll, eine Kernfunktionalität von py.test neu zu implementieren und deswegen wäre ich mit py.test auch glücklicher, wenn es von Haus aus Dekoratoren zur expliziten Markierung von Testfällen nutzen würde. Und bevor Du etwas einwendest: Ich halte Test-Discovery für eine der Kernfunktionalität einer Test-Bibliothek (zusammen mit Ressourcen-Verwaltung und datenbasierten Tests), auch wenn py.test manchmal so tut, als wäre alles einfach nur ein beliebig austauschbares Plugin.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Vielleicht sollte ich mir doch mal `nose` genauer angucken. Danke lunar für Deine Ausführungen - und dass ich mit der Meinung, dass eine Dekorator-Syxntax eleganter wäre, nicht alleine da stehe :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ist halt wieder eine Frage von Convention vs Configuration bzw Explicit vs Implicit. Für beides kann man Argumente finden und beides finde ich sinnvoll wenn es nicht übertrieben wird.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten