Le risposte esistenti sono certamente buone, ma non ho visto nessuno affrontare questo malinteso fondamentale nella domanda:
at any point in time all unit tests must pass
No. Sicuramente, questo non sarà vero. Mentre sto sviluppando software, NCrunch è spesso marrone (errore di compilazione) o rosso (test fallito).
Dove NCrunch deve essere verde (tutti i test che passano) è quando sono pronto a inviare un commit al server di controllo del codice sorgente, perché a quel punto altri potrebbero prendere una dipendenza dal mio codice.
Ciò si alimenta anche nell'argomento della creazione di nuovi test: i test dovrebbero asserire la logica e il comportamento del codice. Condizioni al contorno, condizioni di errore, ecc. Quando scrivo nuove prove, cerco di identificare questi "punti caldi" nel codice.
I test unitari documentano come mi aspetto che venga chiamato il mio codice: precondizioni, risultati attesi, ecc.
Se un test si interrompe dopo una modifica, devo decidere se il codice o il test è in errore.
Come nota a margine, i test unitari vanno talvolta di pari passo con Test Driven Development. Uno dei principi di TDD è che i test non funzionanti sono le tue indicazioni. Quando un test fallisce, è necessario correggere il codice in modo che il test passi. Ecco un esempio concreto di questa settimana:
Sfondo : ho scritto e ora supporta una libreria utilizzata dai nostri sviluppatori che viene utilizzata per convalidare le query Oracle. Avevamo test che affermavano che la query corrispondeva a un valore atteso, il che rendeva il caso importante (non è in Oracle) e approvava allegramente delle query non valide purché corrispondessero completamente al valore previsto.
Invece, la mia libreria analizza la query utilizzando Antlr e una sintassi di Oracle 12c, quindi esegue il wrapping di varie asserzioni sull'albero di sintassi stesso. Cose del tipo, è valido (non sono stati generati errori di analisi), tutti i parametri sono soddisfatti dalla raccolta parametri, tutte le colonne previste lette dal lettore di dati sono presenti nella query, ecc. Tutti questi sono elementi che sono passati a produzione in vari momenti.
Uno dei miei colleghi ingegneri mi ha inviato una query lunedì che aveva fallito (o meglio, aveva avuto successo quando avrebbe dovuto fallire) durante il fine settimana. La mia libreria diceva che la sintassi andava bene, ma si è verificata quando il server ha cercato di eseguirlo. E quando ha esaminato la query, era ovvio il motivo:
UPDATE my_table(
SET column_1 = 'MyValue'
WHERE id_column = 123;
Ho caricato il progetto e aggiunto un test unitario che ha affermato che questa query non dovrebbe essere valida. Ovviamente, il test è fallito.
Successivamente, ho eseguito il debug del test non riuscito, ho fatto il punto del codice in cui mi aspettavo che generasse l'eccezione e ho scoperto che Antlr stava sollevando un errore sul paren aperto, ma non in un modo il codice precedente si aspettava. Ho modificato il codice, verificato che il test fosse ora verde (passando) e che nessun altro si fosse rotto nel processo, commesso e spinto.
Ci sono voluti 20 minuti, e nel processo ho effettivamente migliorato la libreria in modo significativo perché ora supportava un'intera gamma di errori che in precedenza ignorava. Se non avessi i test unitari per la biblioteca, la ricerca e la risoluzione del problema avrebbe potuto richiedere ore.