Unit-Tests bei Methoden ohne jeden Rückgabewert

Das ist eigentlich kein TDD Problem, sondern ein allgemeines Unittest Problem. Je höher die Klassen liegen, desto mehr andere Klassen sind involviert. Wenn man ohne Mocks arbeitet, ist man schnell bei Integrationstests.

[QUOTE=Spacerat]Zum Thema:
Warum muss bei TDD eigentlich immer gemockt werden? Das klingt bei mir immer danach, was bei bygones in der Signatur steht: “…you probably not doing it right.”[/QUOTE]
Nunja, meine Signature hat an sich eine andere Aussage, aber wie Sym schon sagt, eine Klasse kommt nun mal seltenst ohne Abhaengigkeiten aus und diese Abhaengigkeiten muessen in einem Unittest irgendwie bereitgestellt werden.
Im Idealfall kann man die “reale” Implementierung nutzen, im weiteren sollte man versuchen eine Dummy Implementierung zu nehmen, ansonsten eben Mocks und Friends.

Man sollte sich aber, und das ist richtig, davor zuruecknehmen alles zu mocken was nur geht.

[quote=Timothy_Truckle;100785]Das sehe ich anders. Das Mock ist eine Abhänigkeit des zu Testenden Codes, und sagt an sich nichts über den zu testenden Code aus, außer das wir erwarten, dass auf dem Mock eine bestimmte Methode aufgerufen wird.
Oder musst Du wissen, wie Swing implementiert ist, um eingen Listener-Objekte zu registrieren?[/quote]
Geht es denn noch mehr White Box als zu sagen „diese und diese Methoden muessen aufgerufen werden“?
Ich glaube nicht…

Du musst Wissen dass es ein Listener ist, die Methoden Singatur usw.

Vielleicht haben wir nur nicht dieselbe Idee von „White Box“ :wink:

@bygones :
Ja, ich weis. Aber genau dieses Mocking ist doch ein Löwenanteil von “nicht richtig machen”.

Nach allem was ich über TDD gelesen habe, definiert man Schnittstellen (Interfaces) mit mehr oder weniger öffentlichen Methoden (also non private) und testet dann genau nur diese Interfaces statt die konkreten Implementationen.
Also konkret für dieses Problem hier etwa so etwas:

  protected ConsoleApp() {}

  public final void printUsage() {
    printUsage(System.out);
  }

  public abstract void printUsage(PrintStream out);
}```

naja Schnittstellen kan man nicht testen, natuerlich muss man die implementierung testen. es wird keinen Unittest fuer List geben, aber fuer ArrayList.
Wenn du nun einen Unit hast, die es zu testen gilt, so hat diese mit aller Wahrscheinlichkeit eine Abhaengigkeit gegen eine Schnittstelle. D.h. in deinem Test musst du eine Instanz dieser Schnittstelle bereitstellen. Das geht am einfachsten ueber seine Implementierung oder eben, wenn die Implementierung nicht verfuegbar ist ueber einen dummy und wenn dies ebenso nicht moeglich ist, dann ueber einen Mock.
Wie man sieht sollte dieser an letzter Stelle sein und nicht per se immer hergenommen werden.

alle möglichen Zweige durchlaufen

Branchcoverage hört sich besser an als die Realität. Mit den richtigen Tools bekommt man einen Prozentwert heraus, den auch das Management deuten kann.

Das läuft dann so, dass die Leitung Softwareentwicklung auf einem Kongress was von Coverage und Reports hört. Ist ja auch logisch, dass wenn alles „getestet“ wird auch keine Fehler mehr vorhanden sind. Dann wird Geld für Tools ausgegeben die man dann nutzen muss. Und dann darf man so Programmieren, dass auch eine möglichst hohe Coverage herauskommt, bzw. die Tests dazu schreiben.

Also schreibt man Tests die Zweige durchlaufen, die so nie und nimmer vorkommen können um eine hohe Testabdeckung zu bekommen. Und das ganze läuft dann in der Zeit, in der man richtige Arbeit hätte erledigen können.

Das Problem, dass allerdings nicht behoben wird, sind die unnötigen Pfade! Auf Youtube findet sich einer der besten Vorträge zu dem Thema, die ich je gesehen habe. Getting rid of the if with Polymorphism. „The Clean Code Talks – Inheritance, Polymorphism, & Testing“
Aber versucht niemals, sowas tatsächlich umzusetzen! Was mit absoluter Sicherheit das erste ist was ihr zu hören bekommt ist: Schonmal an die Performance gedacht? Immer Objekte erzeugen, wenn ein einfaches If reichen würde.

Wenn die Software mit 100% BranchCoverage immer noch Crap ist, dann kann man es ja noch mit PathCoverage versuchen. Viel Spaß bei nicht trivialen, nicht deterministischen Programmen.

Mocken ist die nächste Geschichte
Hört sich gut an, gibt’s auch richtig coole Tools dazu. Da kann man Prima Kurse dazu verkaufen. Bringen tut es absolut nichts. Wenn man sich mal so richtig lächerlich machen möchte, dann erzählt mal jemandem der in einer Funktionalen Programmiersprache beheimatet ist wie „Cool“ doch Mocking ist. Die Lacher werden auf eurer Seite sein.

Aber sei es drum. Eine Funktion bekommt einen State rein und gibt einen neuen State zurück. Fertig! Damit das funktioniert und auch noch bei nicht trivialen Geschichten läuft muss dass die Sprache auch unterstützen. Scala, Clojure, Haskell, Erlang sind alles Kandidaten die das können.

Und wenn sich Funktionen auf State rein, neuer State raus beschränken, dann wird Testen absolut trivial.

Seiteneffekte wird es immer noch geben und Sie werden nötig bleiben. Allerdings werden Sie drastisch minimiert.

Die Geschichte warum Software Probleme macht ist mMn. nicht, dass die Funktionen nicht das tun, was Sie tun sollen, sondern dass Sie Seiteneffekte verursachen oder von Seiteneffekten behindert werden, dass zu tun, was getan werden muss. Bei Tests lässt sich dass natürlich hervorragend wegoptimieren, so dass man dann erst was mitkriegt, wenn das Programm schon produktiv läuft.

Und wenn ich schon am Ranten bin

static is evil, bzw. Static stört beim Testen, weil man es nicht Wegmocken kann. Oder nur ganz umständlich.

Das ist IMHO Blödsinn. Static Funktionen die keine Seiteneffekte haben und nicht auf statische nicht finale Variabeln zugreifen lassen sich hervorragend testen. Da geht mir richtig einer ab, wenn ich drandenke sowas zu testen. Wenn Methoden auf statische Funktionen zugreifen und diese getestet sind, dann ist das sogar hervorragend und man kann sich das Mocken komplett sparen. Was gibt es besseres als Dinge, die man schon hat zu nutzen? (Tipp: Mocks schreiben ist es nicht)

Quizfrage: Sichtbarkeit von statischen Funktionen, wenn es keine Seiteneffekte gibt?
Antwort: PUBLIC, aber Pssst. nicht weiterverraten.

Singleton bleibt weiterhin evil, da Variablen im Spiel sind.