Das Problem tritt beim TDD auf. Nach einigen Testdurchläufen ändern sich die Rückgabetypen einiger Klassen / Module. Wenn in einer statisch typisierten Programmiersprache ein zuvor verspottetes Objekt in den Tests einer anderen Klasse verwendet wurde und nicht geändert wurde, um die Typänderung widerzuspiegeln, treten Kompilierungsfehler auf.
Bei dynamischen Sprachen wird die Änderung der Rückgabetypen möglicherweise nicht erkannt, und die Tests der anderen Klasse werden weiterhin bestanden. Sicher, es könnte Integrationstests geben, die später fehlschlagen sollten, aber Unit-Tests würden fälschlicherweise bestanden. Gibt es eine Möglichkeit, dies zu vermeiden?
Aktualisierung mit einem trivialen Beispiel (in einer erfundenen Sprache) ...
Version 1:
Calc = {
doMultiply(x, y) {return x * y}
}
//.... more code ....
// On some faraway remote code on a different file
Rect = {
computeArea(l, w) {return Calc.doMultipy(x*y)}
}
// test for Rect
testComputeArea() {
Calc = new Mock()
Calc.expect(doMultiply, 2, 30) // where 2 is the arity
assertEqual(30, computeArea)
}
Nun zu Version 2:
// I change the return types. I also update the tests for Calc
Calc = {
doMultiply(x, y) {return {result: (x * y), success:true}}
}
... Rect löst dann zur Laufzeit eine Ausnahme aus, der Test ist jedoch weiterhin erfolgreich.
quelle
class X
, sondern deren Testsclass Y
davon abhängenX
und somit gegen einen anderen Vertrag getestet werden als gegen das, gegen das es in der Produktion läuft.Antworten:
Bis zu einem gewissen Grad ist dies nur ein Teil der Kosten für das Geschäft mit dynamischen Sprachen. Sie erhalten viel Flexibilität, auch bekannt als "genug Seil, um sich aufzuhängen". Sei vorsichtig damit.
Für mich schlägt das Problem vor, andere Refactoring-Techniken zu verwenden als in einer statisch typisierten Sprache. In einer statischen Sprache ersetzen Sie Rückgabetypen teilweise, damit Sie sich auf den Compiler stützen können, um herauszufinden, welche Stellen möglicherweise beschädigt werden. Dies ist sicher und wahrscheinlich sicherer als das Ändern des vorhandenen Rückgabetyps.
In einer dynamischen Sprache ist dies nicht möglich. Daher ist es viel sicherer, den Rückgabetyp zu ändern, als ihn zu ersetzen. Möglicherweise ändern Sie es, indem Sie Ihre neue Klasse als Mitglied für die Klassen hinzufügen, die es benötigen.
quelle
Wenn sich Ihr Code ändert und Ihre Tests immer noch bestanden werden, stimmt entweder etwas mit Ihren Tests nicht (dh Sie vermissen eine Behauptung), oder der Code hat sich nicht wirklich geändert.
Was meine ich damit? Nun, Ihre Tests beschreiben die Verträge zwischen Teilen Ihres Codes. Wenn der Vertrag "der Rückgabewert muss iterierbar sein" lautet, ist das Ändern des Rückgabewerts von beispielsweise einem Array in eine Liste keine Vertragsänderung und löst daher nicht unbedingt einen Testfehler aus.
Um fehlende Zusicherungen zu vermeiden, können Sie Tools wie die Analyse der Codeabdeckung (sie sagt Ihnen nicht, welche Teile Ihres Codes getestet werden, aber es wird Ihnen sagen, welche Teile definitiv nicht getestet werden), die zyklomatische Komplexität und die NPath-Komplexität verwenden (welche geben Sie eine untere Schranke für die Anzahl der Behauptungen voll C1 und C2 - Code - Abdeckung zu erreichen erforderlich) und Mutation Tester (die inject Mutationen in Ihrem Code wie Drehen
true
auffalse
, negative Zahlen in positive, in Objektenull
usw. und prüfen , ob die macht Tests fehlgeschlagen).quelle