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 accadrà con casi limite.
È quasi come dire:
- Se vuoi sapere cosa fa il metodo, vai a vedere tu stesso le centinaia di righe di 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 sia i valori attesi che quelli effettivi sono diversi da quelli che mi aspettavo davvero .
Questo significa anche che non è necessario aggiungere test come:
assert(3, math.add(1, 2));
assert(4, math.add(2, 2));
Non aiutano nessuno dei due, o almeno, una volta che hai fatto la prima affermazione, la seconda non porta nulla di utile.
Invece, che dire di:
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 è autoesplicativo e dannatamente utile sia per te che per la persona che manterrà il codice sorgente in seguito.Immagina che questa persona esegua una leggera modifica per math.add
semplificare il codice e ottimizzare le prestazioni e vedere i risultati 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 metodo appena 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 numero lungo.
Allo stesso modo, ottenere il valore effettivo 4.141592
alla prima asserzione è autoesplicativo: sai che il metodo dovrebbe affrontare 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 di:
assert(numeric.Infinity, math.add(numeric.Infinity, 1));
Anche autoesplicativo: vuoi che il tuo metodo sia in grado di affrontare correttamente l'infinito. Andando 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.");
}
How does unit testing work?
Nessuno lo sa davvero :)