Prendendo il tuo esempio (con un po 'di refactoring),
assert(a + b, math.add(a, b));
non aiuta a:
- capire come
math.add
si comporta internamente,
- sapere cosa succederà con i casi limite.
È più o meno come dire:
- Se vuoi sapere che cosa fa il metodo, vai a vedere le centinaia di righe del codice sorgente (perché, sì,
math.add
può contenere centinaia di LOC; vedi sotto).
- Non mi preoccupo di sapere se il metodo funziona correttamente. Va bene se entrambi i valori attesi e quelli effettivi sono diversi da ciò che mi aspettavo .
Questo significa anche che non devi aggiungere test come:
assert(3, math.add(1, 2));
assert(4, math.add(2, 2));
Non aiutano né, o almeno, una volta fatta la prima asserzione, la seconda non porta nulla di utile.
Invece, che dire:
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.");
Questo è auto-esplicativo e dannatamente utile sia per te che per la persona che manterrà il codice sorgente in seguito. Immagina che questa persona apporti una leggera modifica a math.add
per semplificare il codice e ottimizzare le prestazioni e vede il risultato del test come:
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
questa persona capirà immediatamente che il nuovo metodo modificato dipende dall'ordine degli argomenti: se il primo argomento è un numero intero e il secondo è un numero lungo, il risultato sarebbe un numero intero, mentre era previsto un valore numerico lungo .
Allo stesso modo, ottenere il valore effettivo di 4.141592
alla prima asserzione è autoesplicativo: sai che il metodo dovrebbe gestire una grande precisione , ma in realtà, fallisce.
Per lo stesso motivo, due asserzioni seguenti possono avere senso in alcune lingue:
// 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));
Inoltre, che dire:
assert(numeric.Infinity, math.add(numeric.Infinity, 1));
Anche auto-esplicativo: vuoi che il tuo metodo sia in grado di gestire correttamente l'infinito. Passare oltre l'infinito o lanciare un'eccezione non è un comportamento previsto.
O forse, a seconda della lingua, questo avrà più senso?
/**
* 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.");
}