Ich habe gelesen diese Stelle darüber, wie man private Methoden testet. Ich teste sie normalerweise nicht, weil ich immer dachte, dass es schneller ist, nur öffentliche Methoden zu testen, die von außerhalb des Objekts aufgerufen werden. Testen Sie private Methoden? Sollte ich sie immer testen?
Antworten
Zu viele Anzeigen?Ich habe das Konzept des Einheitstests nie verstanden, aber jetzt weiß ich, was das Ziel ist.
Ein Unit Test ist kein vollständiger Test . Es ist also kein Ersatz für QA und manuelle Tests. Das Konzept von TDD ist in dieser Hinsicht falsch, da man nicht alles testen kann, einschließlich privater Methoden, aber auch Methoden, die Ressourcen verwenden (insbesondere Ressourcen, über die wir keine Kontrolle haben). TDD stützt seine Qualität auf etwas, das nicht erreicht werden kann.
Ein Unit-Test ist eher ein Pivot-Test Sie markieren einen beliebigen Drehpunkt, und das Ergebnis des Drehpunkts sollte dasselbe bleiben.
Public vs. Private ist keine nützliche Unterscheidung für welche Apis von Ihren Tests aufgerufen werden sollen, ebenso wenig wie Methode vs. Klasse. Die meisten testbaren Einheiten sind in einem Kontext sichtbar, aber in anderen verborgen.
Was zählt, sind Deckung und Kosten. Sie müssen die Kosten minimieren und gleichzeitig die Abdeckungsziele Ihres Projekts erreichen (Zeile, Zweig, Pfad, Block, Methode, Klasse, Äquivalenzklasse, Anwendungsfall... was immer das Team entscheidet).
Verwenden Sie also Tools, um die Abdeckung sicherzustellen, und entwerfen Sie Ihre Tests so, dass sie möglichst wenig Kosten verursachen (kurz und langfristig ).
Machen Sie die Tests nicht teurer als nötig. Wenn es am billigsten ist, nur öffentliche Zugangspunkte zu testen, tun Sie das. Wenn es am günstigsten ist, private Methoden zu testen, tun Sie das.
Wenn Sie mehr Erfahrung haben,
Wenn ich feststelle, dass die private Methode groß oder komplex oder wichtig genug ist, um eigene Tests zu erfordern, füge ich sie einfach in eine andere Klasse ein und mache sie dort öffentlich (Method Object). Dann kann ich die zuvor private und nun öffentliche Methode, die nun in einer eigenen Klasse lebt, problemlos testen.
Ein wichtiger Punkt ist
Wenn wir testen, um die Korrektheit der Logik sicherzustellen, und eine private Methode eine Logik trägt, sollten wir sie testen. Oder etwa nicht? Warum lassen wir das also aus?
Das Schreiben von Tests auf der Grundlage der Sichtbarkeit von Methoden ist eine völlig irrelevante Idee.
Umgekehrt
Auf der anderen Seite ist der Aufruf einer privaten Methode außerhalb der ursprünglichen Klasse ein großes Problem. Außerdem gibt es in einigen Mocking-Tools Einschränkungen für das Mocking einer privaten Methode. (Bsp: Mockito )
Es gibt zwar einige Tools wie Power Mock die das unterstützt, ist es eine gefährliche Operation. Der Grund dafür ist, dass es die JVM hacken muss, um das zu erreichen.
Ein möglicher Ausweg ist (Wenn Sie Testfälle für private Methoden schreiben wollen)
Erklären Sie die privat Methoden wie geschützt . In manchen Situationen ist dies jedoch nicht sinnvoll.
Die Antwort auf die Frage "Sollte ich private Methoden testen?" lautet "....... manchmal". Normalerweise sollten Sie gegen die Schnittstelle Ihrer Klassen testen.
- Einer der Gründe dafür ist, dass man für ein Feature keine doppelte Abdeckung braucht.
- Ein weiterer Grund ist, dass Sie, wenn Sie private Methoden ändern, jeden Test für diese Methoden aktualisieren müssen, auch wenn sich die Schnittstelle Ihres Objekts nicht geändert hat.
Hier ist ein Beispiel:
class Thing
def some_string
one + two
end
private
def one
'aaaa'
end
def two
'bbbb'
end
end
class RefactoredThing
def some_string
one + one_a + two + two_b
end
private
def one
'aa'
end
def one_a
'aa'
end
def two
'bb'
end
def two_b
'bb'
end
end
で RefactoredThing
Sie haben jetzt 5 Tests, von denen Sie 2 für das Refactoring aktualisieren mussten, aber die Funktionalität Ihres Objekts hat sich nicht wirklich geändert. Nehmen wir an, die Dinge sind komplexer als das und Sie haben eine Methode, die die Reihenfolge der Ausgabe definiert, wie z. B.:
def some_string_positioner
if some case
elsif other case
elsif other case
elsif other case
else one more case
end
end
Dies sollte nicht von einem externen Benutzer ausgeführt werden, aber Ihre kapselnde Klasse kann zu schwer sein, um so viel Logik immer und immer wieder durchlaufen zu lassen. In diesem Fall vielleicht würden Sie eher extrahieren Sie diese in eine separate Klasse, geben Sie dieser Klasse eine Schnittstelle und testen gegen sie.
Und schließlich, nehmen wir an, Ihr Hauptobjekt ist superschwer, und die Methode ist ziemlich klein, und Sie müssen wirklich sicherstellen, dass die Ausgabe korrekt ist. Sie denken: "Ich muss diese private Methode testen!". Haben Sie daran gedacht, dass Sie Ihr Objekt vielleicht leichter machen können, indem Sie einen Teil der schweren Arbeit als Initialisierungsparameter übergeben? Dann können Sie etwas Leichteres übergeben und dagegen testen.