I test sono lì per supportare e garantire la programmazione difensiva
La programmazione difensiva protegge l'integrità del sistema in fase di esecuzione.
I test sono strumenti diagnostici (principalmente statici). In fase di esecuzione, i test non sono in vista. Sono come le impalcature utilizzate per montare un alto muro di mattoni o una cupola di roccia. Non lasci parti importanti fuori dalla struttura perché hai un'impalcatura che lo sostiene durante la costruzione. Hai un'impalcatura che lo sostiene durante la costruzione per facilitare l' inserimento di tutti i pezzi importanti.
EDIT: un'analogia
Che dire di un'analogia con i commenti nel codice?
I commenti hanno il loro scopo, ma possono essere ridondanti o addirittura dannosi. Ad esempio, se si inserisce una conoscenza intrinseca del codice nei commenti , quindi si modifica il codice, i commenti diventano irrilevanti nella migliore delle ipotesi e dannosi nella peggiore.
Quindi supponiamo che tu abbia messo molta conoscenza intrinseca della tua base di codice nei test, come MethodA non può prendere nulla e l'argomento di MethodB deve essere > 0
. Quindi il codice cambia. Null va bene per A ora e B può assumere valori piccoli come -10. I test esistenti ora sono funzionalmente errati, ma continueranno a passare.
Sì, dovresti aggiornare i test mentre aggiorni il codice. Dovresti anche aggiornare (o rimuovere) i commenti mentre aggiorni il codice. Ma sappiamo tutti che queste cose non sempre accadono e che vengono fatti degli errori.
I test verificano il comportamento del sistema. Tale comportamento effettivo è intrinseco al sistema stesso, non intrinseco ai test.
Che cosa potrebbe andare storto?
L'obiettivo per quanto riguarda i test è di pensare a tutto ciò che potrebbe andare storto, scrivere un test per verificarne il comportamento corretto, quindi creare il codice di runtime in modo che superi tutti i test.
Ciò significa che il punto è la programmazione difensiva .
TDD guida la programmazione difensiva, se i test sono completi.
Più test, guidando una programmazione più difensiva
Quando i bug vengono inevitabilmente trovati, vengono scritti più test per modellare le condizioni che manifestano il bug. Quindi il codice viene corretto, con il codice per far passare quei test e i nuovi test rimangono nella suite di test.
Una buona serie di test sta per passare argomenti validi e negativi a una funzione / metodo e si aspettano risultati coerenti. Questo, a sua volta, significa che il componente testato utilizzerà controlli preliminari (programmazione difensiva) per confermare gli argomenti passati.
In generale ...
Ad esempio, se un argomento null a una determinata procedura non è valido, almeno un test passerà un null e si aspetterà un'eccezione / errore "argomento null non valido" di qualche tipo.
Almeno un altro test sta per passare un argomento valido , ovviamente - o passare in rassegna un array grande e passare ennesimi argomenti validi - e confermare che lo stato risultante è appropriato.
Se un test non passa quell'argomento nullo e viene schiaffeggiato con l'eccezione prevista (e quell'eccezione è stata lanciata perché il codice ha controllato in modo difensivo lo stato passato ad esso), allora il null può finire assegnato a una proprietà di una classe o sepolto in una raccolta di qualche tipo dove non dovrebbe essere.
Ciò potrebbe causare comportamenti imprevisti in alcune parti del sistema completamente diverse a cui viene passata l'istanza della classe, in alcune impostazioni geografiche distanti dopo che il software è stato spedito . E questo è il genere di cose che stiamo effettivamente cercando di evitare, giusto?
Potrebbe anche essere peggio. L'istanza di classe con lo stato non valido può essere serializzata e archiviata, solo per causare un errore quando viene ricostituita per un utilizzo successivo. Accidenti, non lo so, forse è un sistema di controllo meccanico di qualche tipo che non può riavviarsi dopo un arresto perché non può deserializzare il proprio stato di configurazione persistente. Oppure l'istanza di classe potrebbe essere serializzata e passata a un sistema completamente diverso creato da un'altra entità e tale sistema potrebbe arrestarsi in modo anomalo.
Soprattutto se i programmatori di quell'altro sistema non codificassero in modo difensivo.