Biorąc twój przykład (z odrobiną refaktoryzacji),
assert(a + b, math.add(a, b));
nie pomaga:
- zrozumieć, jak się
math.add
zachowuje wewnętrznie,
- wiedzieć, co się stanie z przypadkowymi przypadkami.
To prawie tak, jak powiedzenie:
- Jeśli chcesz wiedzieć, co robi metoda, idź i zobacz setki wierszy kodu źródłowego (ponieważ tak,
math.add
może zawierać setki LOC; patrz poniżej).
- Nie przejmuję się, czy metoda działa poprawnie. Jest ok, jeśli zarówno oczekiwane, jak i rzeczywiste wartości różnią się od tego, czego naprawdę oczekiwałem .
Oznacza to również, że nie musisz dodawać testów takich jak:
assert(3, math.add(1, 2));
assert(4, math.add(2, 2));
Nie pomagają ani, przynajmniej, gdy raz uczynisz pierwsze twierdzenie, drugie nie przyniesie nic pożytecznego.
Zamiast tego:
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.");
Jest to zrozumiałe i cholernie pomocne zarówno dla ciebie, jak i dla osoby, która zachowa kod źródłowy później. Wyobraź sobie, że ta osoba wprowadza niewielką modyfikację, aby math.add
uprościć kod i zoptymalizować wydajność, i widzi wynik testu w następujący sposób:
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
osoba ta natychmiast zrozumie, że nowo zmodyfikowana metoda zależy od kolejności argumentów: jeśli pierwszy argument jest liczbą całkowitą, a drugi długą liczbą, wynik będzie liczbą całkowitą, podczas gdy oczekiwano długiej liczby.
W ten sam sposób uzyskanie rzeczywistej wartości 4.141592
pierwszego stwierdzenia jest oczywiste: wiesz, że oczekuje się, że metoda poradzi sobie z dużą precyzją , ale tak naprawdę się nie powiedzie.
Z tego samego powodu w niektórych językach mogą mieć sens dwa następujące stwierdzenia:
// 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));
A co z:
assert(numeric.Infinity, math.add(numeric.Infinity, 1));
Nie trzeba tłumaczyć: chcesz, aby twoja metoda była w stanie poprawnie radzić sobie z nieskończonością. Wyjście poza nieskończoność lub zgłoszenie wyjątku nie jest oczekiwanym zachowaniem.
A może, w zależności od języka, będzie to miało większy sens?
/**
* 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?
Nikt tak naprawdę nie wie :)