Ist es eine schlechte Praxis, die Unit-Tests für eine Klasse zu trennen? [geschlossen]

8

Meine Klassen haben normalerweise maximal 5-20 Methoden, was bedeutet, dass die Klasse mit den Komponententests ungefähr das Doppelte der Methoden hat (Zählen von dataProvidern, setUp, ...).

Ich habe darüber nachgedacht, die Tests in 2-3 Klassen zu unterteilen, denn selbst wenn ich versuche, dem Prinzip der Einzelverantwortung zu folgen, bevorzuge ich 2 Testklassen mit jeweils 10 Methoden als eine mit 20.

Ist es eine schlechte Praxis? Ist es gut, alle Tests für eine Klasse in nur einer zu haben, obwohl die Testklasse vertikal wächst?

Luisandani
quelle
4
Zu viele Unit-Tests scheinen ein Symptom dafür zu sein, dass eine Klasse gegen das Prinzip der Einzelverantwortung verstößt . Anstatt die Symptome zu umgehen, sprechen Sie die Grundursache in einem Klassendesign an
Mücke
Ein Vorteil, wenn Sie alle Ihre Tests in einer Datei haben, besteht darin, dass einige IDEs anhand ihrer Namen automatisch erkennen können, welche Tests welchen Klassen zugeordnet sind. Aber irgendwann ist dies keine große Überlegung im Vergleich dazu, Ihre Tests gut organisiert zu halten.
Kevin
Vielen Dank, Mücke, für Ihre Antwort. Ich habe die Frage aktualisiert, um sie nur auf die getrennten Tests zu konzentrieren.
Luisandani

Antworten:

18

Um die spezifische Frage zu beantworten, ist es absolut möglich, dass das Gruppieren von Tests in mehrere Klassen eine gute Entscheidung ist, wenn die zu testende Klasse gut gestaltet ist.

Der Unit-Test-Code ist wie jeder andere Code: Er sollte guten Konstruktionsprinzipien folgen ( DRY , GRASP , KISS , SOLID , YAGNI usw.). Da die Logik, aus der der Testcode besteht, oft einfacher ist als die Domänenlogik, werden viele der spezifischen Punkte nicht so häufig angesprochen, aber denken Sie beim Schreiben Ihrer Tests trotzdem daran.

Es gibt einige Grundsätze, die leicht in den Sinn kommen, wenn Sie über Ihre Frage nachdenken:

Lesbarkeit

Wenn ein Test einmal geschrieben ist, müssen Sie ihn im Idealfall nie wieder ansehen. Das Gleiche gilt jedoch für jeden Code. Die Realität ist, dass sich die Anforderungen ändern, sodass wir Code viel mehr lesen als schreiben. Selbst wenn Sie Ihr Bestes geben, stellen Sie möglicherweise fest, dass der von Ihnen geschriebene Test nicht ganz bestätigt hat, was Sie dachten. An diesem Punkt müssen Sie wieder hineingehen und herausfinden, was falsch war. Es wird schwierig sein, diese Testmethode in einer Klasse von 40-50 Testmethoden zu finden, ganz zu schweigen von der Komplikation der Benennung dieser Methoden, damit sie leicht unterschieden werden können.

Hoher Zusammenhalt

Jede Testklasse (wie jede andere Klasse) sollte einen klaren Fokus haben. Wenn Sie viele verschiedene Testfälle für eine bestimmte Methode der zu testenden Klasse haben, z. B. wenn ein bestimmter Test eine einzelne Sache überprüft, ordnen Sie diese Testmethoden einer separaten Klasse zu und benennen Sie sie, um ihren Fokus widerzuspiegeln.

Mike Partridge
quelle
3
Vielleicht möchten Sie sich einen Test ansehen, auch wenn sich keine Anforderungen ändern - nur um zu verstehen, wie die getestete Klasse beispielsweise verwendet werden soll.
Paŭlo Ebermann
7

Es ist fast unerheblich, wie Ihre Unit-Tests organisiert sind, im Vergleich dazu, dass sie überhaupt durchgeführt werden.

Ein Modul oder eine Klasse von Geschäftscode muss als Einheit verstanden und weiterentwickelt werden. Dies ist der Hauptgrund, warum wir uns bemühen, es kohärent, als Ganzes leicht verständlich usw. zu machen. Eine Testsuite ist nur eine Sammlung von Fällen, die alle bestehen müssen. Sie haben keine besondere Beziehung zueinander . Im Idealfall müssen Sie sich nie wieder damit befassen. Wenn Sie dies tun, müssen Sie normalerweise weitere Tests hinzufügen, die wiederum keine besondere Beziehung zu einem anderen Test haben und die nur vom Unit-Test-Framework vom Client-Code aufgerufen werden.

Daher ist die Frage, wie die Klassen mit Komponententests organisiert werden sollen, viel weniger kritisch als die Frage, wie die Klassen organisiert werden, aus denen Ihre Anwendung selbst besteht. Sie sollten sie sowieso nicht als gut strukturierte Makrostruktur behandeln.

Kilian Foth
quelle
Obwohl ich denke, dass Sie im Allgemeinen Recht haben, gibt es nur wenige Dinge, die schlimmer sind als fehlerhafte, zerbrechliche, unklare und schwer zu befolgende Tests. Spaghetti-Testcode ist nicht großartig.
Paul Draper
3

Legen Sie die Tests in einer Datei ab. Normalerweise hätte ich für jede Klassendatei eine Testdatei. Fügen Sie normalerweise "Tests" an den Dateinamen an.

Wenn es beispielsweise eine Klasse namens "Foo" gibt, gibt es eine entsprechende "FooTests" -Datei. Auf diese Weise besteht für jede Codedatei eine 1: 1-Beziehung zwischen der Codedatei und der Testdatei.

Dies sorgt für Konsistenz und erleichtert Entwicklern das Auffinden und Aktualisieren der Tests. Tests werden normalerweise von der Codeanalyse / -metrik ausgeschlossen. Wenn die Datei also groß ist, wird die allgemeine Code-Integritätsmetrik nicht beeinträchtigt. Daher halte ich es nicht für eine schlechte Form, eine Testdatei mit viel Unit-Test-Code zu haben.

Jon Raynor
quelle
3

Wenn wir sagen, dass die Definition von schlechter Praxis in der Softwareentwicklung etwas ist, das Ihnen nicht hilft, mit Veränderungen umzugehen und sie zu verkapseln, dann würde ich sagen, dass es schlechte Praxis ist , Ihre Klassen und Tests nicht in einer Eins-zu-Eins-Beziehung zu halten . Es ist ein Code-Geruch, der aufgrund der unten genannten Dinge auftreten kann.

Offensichtlich gibt es Ausnahmen wie bei allem anderen, aber denken Sie daran, wenn Sie Ihre Tests schreiben.

Meine Klassen haben normalerweise maximal 5-20 Methoden.

Wenn eine Ihrer Klassen 20 (oder etwas weniger) Methoden hat, zeigt mir das, dass die Klasse überhaupt zu viel tut . Hier sollten Unit-Tests darauf hinweisen, dass Sie Ihre Klasse möglicherweise etwas weiter aufteilen und die Verantwortung verteilen müssen, bevor Sie mit dem Testen beginnen.

Um sie in derselben Klasse zu halten oder nicht, würde ich vorschlagen, wenn möglich zu versuchen , sie in einer Klasse zu halten, da dies besser verständlich ist - eine Eins-zu-eins-Verbindung ist nach langer Zeit leicht zu erfassen . Nur aus Erfahrung.

Wenn Sie feststellen, dass die Komponententests selbst bei 5 oder weniger Methoden sehr umfangreich sind , bedeutet dies, dass Ihr Setup-Code zu viel tut oder Ihre Objekte ungewöhnlich groß sind .

Wenn Sie das Builder-Muster zum Erstellen Ihrer Objekte noch nicht ausprobiert haben, kann dies den Code für das Erstellen Ihrer Objekte drastisch reduzieren, bevor Sie sie testen. Dadurch wird die Unit-Test-Klasse kürzer und Sie müssen sie weniger in mehrere Klassen unterteilen.

AvetisG
quelle
Dies ist ein ausgezeichneter Rat, aber keine Antwort auf die Frage. (Immer noch positiv bewertet)
Jon Raynor
@ JonRaynor danke! Ich habe gerade meine Antwort mit einer Schlussfolgerung aktualisiert und speziell die Frage beantwortet.
AvetisG
Könnten Sie bitte die Abwertung näher erläutern?
AvetisG
1
@AvetisG: Die Leute müssen ihre Abstimmungen nicht näher erläutern und es ist unfair, sie darum zu bitten. Aber ich werde versuchen, Ihnen zu helfen ... Nur der erste Absatz hier versucht sogar, die Frage zu beantworten. Der Rest ist eine Meinung, die manche Leute nicht teilen würden. Ich persönlich stimme Ihrer Meinung zu, aber ich stimme nicht dem einen Absatz zu, der für die Frage relevant ist, und ich sehe die Verbindung, die Sie herstellen, nicht. Mikes Antwort ist richtig: "Jede Testklasse (wie jede andere Klasse) sollte einen klaren Fokus haben." Dies kann der gleiche Schwerpunkt sein wie für Ihre zu testenden Klassen.
pdr
@pdr das macht Sinn. Vielen Dank für die Erweiterung.
AvetisG