Ich habe eine Reihe von Klassen, die sich mit der Validierung von Werten befassen. Beispielsweise RangeValidator
prüft eine Klasse, ob ein Wert innerhalb des angegebenen Bereichs liegt.
Jede Validator-Klasse enthält zwei Methoden: eine is_valid(value)
, die einen bestimmten Wert zurückgibt True
oder von diesem False
abhängig ist und ensure_valid(value)
die nach einem bestimmten Wert sucht und entweder nichts unternimmt, wenn der Wert gültig ist, oder eine bestimmte Ausnahme auslöst, wenn der Wert nicht den vordefinierten Regeln entspricht.
Mit dieser Methode sind derzeit zwei Komponententests verbunden:
Derjenige, der einen ungültigen Wert übergibt und sicherstellt, dass die Ausnahme ausgelöst wurde.
def test_outside_range(self): with self.assertRaises(demo.ValidationException): demo.RangeValidator(0, 100).ensure_valid(-5)
Derjenige, der einen gültigen Wert übergibt.
def test_in_range(self): demo.RangeValidator(0, 100).ensure_valid(25)
Obwohl der zweite Test seine Aufgabe erfüllt - schlägt fehl, wenn die Ausnahme ausgelöst wird, und ist erfolgreich, wenn ensure_valid
nichts ausgelöst wird -, sieht die Tatsache, dass kein assert
s enthalten ist, seltsam aus. Jemand, der solchen Code liest, würde sich sofort fragen, warum es einen Test gibt, der scheinbar nichts tut.
Ist dies eine aktuelle Praxis beim Testen von Methoden, die keinen Wert zurückgeben und keine Nebenwirkungen haben? Oder sollte ich den Test anders schreiben? Oder einfach einen Kommentar hinterlassen, der erklärt, was ich tue?
quelle
self
Referenz) und kein Ergebnis zurückgibt, ist dies keine reine Funktion.void
in vielen Sprachen aufgerufen wird und alberne Regeln enthält.). Alternativ können Sie eine unendliche Zahl angeben Schleife (die auch als „Rückkehr kein Ergebnis“ funktioniert wirklich bedeutet , lieferte keine Ergebnisse.unit -> unit
die Einheit als Standarddatentyp betrachtet, anstatt etwas magisch Besonderes. Leider gibt es nur Einheit zurück und tut nichts anderes.Antworten:
Die meisten Test-Frameworks haben eine explizite Aussage für "
expect(() => {}).not.toThrow();
Wirft nicht", z. B. hat Jasmine und nUnit und Freunde haben auch eine.quelle
Dies hängt stark von der verwendeten Sprache und dem verwendeten Framework ab. Apropos
NUnit
, es gibtAssert.Throws(...)
Methoden. Sie können ihnen eine Lambda-Methode übergeben:die innerhalb der ausgeführt wird
Assert.Throws
. Der Aufruf des Lambda wird höchstwahrscheinlich von einemtry { } catch { }
Block eingeschlossen, und die Assertion schlägt fehl, wenn eine Ausnahme abgefangen wird.Wenn Ihr Framework diese Mittel nicht bietet, können Sie es umgehen, indem Sie den Aufruf selbst abschließen (ich schreibe in C #):
Dadurch wird die Absicht klarer, aber der Code wird bis zu einem gewissen Grad unübersichtlich. (Natürlich können Sie all diese Dinge in eine Methode einwickeln.) Am Ende liegt es an Ihnen.
Bearbeiten
Wie Doc Brown in den Kommentaren hervorhob, bestand das Problem nicht darin, anzuzeigen, dass die Methode ausgelöst wird, sondern, dass sie nicht ausgelöst wird. In NUnit gibt es auch eine Behauptung dafür
quelle
Fügen Sie einfach einen Kommentar hinzu, um zu verdeutlichen, warum keine Zusicherung erforderlich ist und warum Sie sie nicht vergessen haben.
Wie Sie in den anderen Antworten sehen können, macht alles andere den Code komplizierter und übersichtlicher. Mit dem Kommentar dort werden andere Programmierer die Absicht des Tests kennen.
Davon abgesehen sollte diese Art von Test eine Ausnahme sein (kein Wortspiel beabsichtigt). Wenn Sie feststellen, dass Sie so etwas regelmäßig schreiben, werden Sie wahrscheinlich anhand der Tests feststellen, dass das Design nicht optimal ist.
quelle
Sie können auch behaupten, dass einige Methoden ordnungsgemäß aufgerufen (oder nicht aufgerufen) werden.
Zum Beispiel:
In Ihrem Test:
quelle