Nehmen Sie Ihr Beispiel (mit ein bisschen Refactoring),
assert(a + b, math.add(a, b));
hilft nicht
- verstehen, wie
math.add
sich intern verhält,
- wissen, was mit Randfällen passieren wird.
Es ist so ziemlich so, als würde man sagen:
- Wenn Sie wissen möchten, was die Methode bewirkt, sehen Sie sich die Hunderte von Zeilen Quellcode selbst an (denn ja, es
math.add
können Hunderte von LOC enthalten sein; siehe unten).
- Ich muss nicht wissen, ob die Methode richtig funktioniert. Es ist in Ordnung, wenn sowohl die erwarteten als auch die tatsächlichen Werte von den Erwartungen abweichen .
Dies bedeutet auch, dass Sie keine Tests wie die folgenden hinzufügen müssen:
assert(3, math.add(1, 2));
assert(4, math.add(2, 2));
Sie helfen auch nicht, oder zumindest, wenn Sie die erste Behauptung aufgestellt haben, bringt die zweite nichts Sinnvolles.
Was ist stattdessen mit:
const numeric Pi = 3.1415926535897932384626433832795;
const numeric Expected = 4.1415926535897932384626433832795;
assert(Expected, math.add(Pi, 1),
"Adding an integer to a long numeric doesn't give a long numeric result.");
assert(Expected, math.add(1, Pi),
"Adding a long numeric to an integer doesn't give a long numeric result.");
Dies ist selbsterklärend und sowohl für Sie als auch für die Person, die den Quellcode später pflegen wird, verdammt hilfreich.Stellen Sie sich vor, diese Person nimmt eine geringfügige Änderung an der vor math.add
, um den Code zu vereinfachen und die Leistung zu optimieren, und sieht das Testergebnis wie folgt aus :
Test TestNumeric() failed on assertion 2, line 5: Adding a long numeric to an
integer doesn't give a long numeric result.
Expected value: 4.1415926535897932384626433832795
Actual value: 4
Diese Person wird sofort verstehen, dass die neu geänderte Methode von der Reihenfolge der Argumente abhängt: Wenn das erste Argument eine Ganzzahl und das zweite eine lange Zahl ist, ist das Ergebnis eine Ganzzahl, während eine lange Zahl erwartet wurde.
Auf die gleiche Weise erhält man den tatsächlichen Wert von 4.141592
ist es selbsterklärend der ersten Behauptung zu ermitteln: Sie wissen, dass die Methode eine große Präzision aufweisen muss , aber tatsächlich scheitert sie.
Aus dem gleichen Grund können zwei der folgenden Aussagen in einigen Sprachen sinnvoll sein:
// We don't expect a concatenation. `math` library is not intended for this.
assert(0, math.add("Hello", "World"));
// We expect the method to convert every string as if it was a decimal.
assert(5, math.add("0x2F", 5));
Und was ist mit:
assert(numeric.Infinity, math.add(numeric.Infinity, 1));
Auch selbsterklärend: Sie möchten, dass Ihre Methode mit der Unendlichkeit richtig umgehen kann. Gehen Unendlichkeit hinauszugehen oder eine Ausnahme auszulösen, ist kein erwartetes Verhalten.
Oder macht das je nach Sprache mehr Sinn?
/**
* Ensures that when adding numbers which exceed the maximum value, the method
* fails with OverflowException, instead of restarting at numeric.Minimum + 1.
*/
TestOverflow()
{
UnitTest.ExpectException(ofType(OverflowException));
numeric result = math.add(numeric.Maximum, 1));
UnitTest.Fail("The tested code succeeded, while an OverflowException was
expected.");
}
How does unit testing work?
Niemand weiß es wirklich :)