Assertimenti sono utili per informarti su lo stato interno del programma . Ad esempio, che le tue strutture di dati hanno uno stato valido, ad es. Che una struttura di dati Time
non manterrà il valore di 25:61:61
. Le condizioni controllate da asserti sono:
-
Precondizioni, che assicurano che il chiamante mantenga il suo contratto,
-
Post-condizioni, che assicurano che il destinatario mantenga il contratto, e
-
Invarianti, che assicurano che la struttura dati contenga sempre alcune proprietà dopo il ritorno della funzione. Un invariante è una condizione che è una precondizione e una postcondizione.
Test unitari sono utili per informarti su il comportamento esterno del modulo . Il tuo Stack
potrebbe avere uno stato coerente dopo che è stato chiamato il metodo push()
, ma se la dimensione dello stack non aumenta di tre dopo essere stata chiamata tre volte, allora si tratta di un errore. (Ad esempio, il caso banale in cui l'implementazione push()
non corretta controlla solo le asserzioni e le uscite.)
A rigor di termini, la differenza principale tra asserzioni e test unitari è che i unit test hanno dati di test (valori per far funzionare il programma), mentre gli asserzioni no. Cioè, puoi eseguire automaticamente i tuoi test unitari, mentre non puoi dire lo stesso per le asserzioni. Per il gusto di questa discussione, ho assunto che tu stia parlando dell'esecuzione del programma nel contesto di test di funzione di ordine superiore (che eseguono l'intero programma e non guidano moduli come i test di unità). Se non si parla di test automatici come mezzo per "vedere gli input reali", allora il valore risiede nell'automazione, e quindi i test unitari vincono. Se stai parlando di questo nel contesto dei test di funzione (automatici), vedi sotto.
Ci può essere qualche sovrapposizione in ciò che viene testato. Ad esempio, una postcondizione di Stack
può effettivamente affermare che la dimensione dello stack aumenta di uno. Ma ci sono dei limiti a ciò che può essere eseguito in quella affermazione: dovrebbe anche controllare che l'elemento superiore sia quello che è stato appena aggiunto?
Per entrambi, l'obiettivo è aumentare la qualità. Per i test unitari, l'obiettivo è trovare i bug. Per le asserzioni, l'obiettivo è rendere il debug più semplice osservando gli stati dei programmi non validi non appena si verificano.
Si noti che la tecnica né verifica la correttezza. In effetti, se conduci un test unitario con l'obiettivo di verificare che il programma sia corretto, probabilmente otterrai un test poco interessante che sai funzionerà. È un effetto psicologico: farai qualsiasi cosa per raggiungere il tuo obiettivo. Se il tuo obiettivo è trovare bug, le tue attività lo rifletteranno.
Entrambi sono importanti e hanno i loro scopi.
[Come nota finale sulle asserzioni: per ottenere il massimo valore, è necessario utilizzarle in tutti i punti critici del programma e non in alcune funzioni chiave. Altrimenti, la fonte originale del problema potrebbe essere stata mascherata e difficile da rilevare senza ore di debug.]