Contrariamente alle altre risposte, è importante notare che alcuni modi di test possono diventare fragili quando il sistema sotto test (SUT) viene refactored, se il test è whitebox.
Se sto usando un framework beffardo che verifica l' ordine dei metodi chiamati sulle simulazioni (quando l'ordine è irrilevante perché le chiamate sono prive di effetti collaterali); quindi se il mio codice è più pulito con quelle chiamate di metodo in un ordine diverso e io refactoring, il mio test si interromperà. In generale, le beffe possono introdurre fragilità nei test.
Se sto controllando lo stato interno del mio SUT esponendo i suoi membri privati o protetti (potremmo usare "amico" in Visual Basic, o aumentare il livello di accesso "interno" e usare "internalsvisibleto" in c #; in molte lingue OO, tra cui c # una " sottoclasse specifica per il test " potrebbe essere utilizzata), quindi all'improvviso lo stato interno della classe avrà importanza - potresti refactoring della classe come una scatola nera, ma i test della scatola bianca falliranno. Supponiamo che un singolo campo venga riutilizzato per significare cose diverse (non una buona pratica!) Quando il SUT cambia stato - se lo dividiamo in due campi, potrebbe essere necessario riscrivere i test non funzionanti.
Le sottoclassi specifiche del test possono anche essere utilizzate per testare metodi protetti, il che può significare che un refattore dal punto di vista del codice di produzione è una svolta dal punto di vista del codice di test. Spostare alcune righe all'interno o all'esterno di un metodo protetto potrebbe non avere effetti collaterali sulla produzione, ma interrompere un test.
Se utilizzo " hook di test " o qualsiasi altro codice di compilazione specifico o condizionale del test, può essere difficile garantire che i test non vengano interrotti a causa delle fragili dipendenze dalla logica interna.
Quindi, per evitare che i test si accoppino ai dettagli interni intimi del SUT, può aiutare a:
- Usa stub piuttosto che beffe, ove possibile. Per maggiori informazioni consultare il blog di Fabio Periera sui test tautologici e il mio blog sui test tautologici .
- Se si usano beffe, evitare di verificare l'ordine dei metodi chiamati, a meno che non sia importante.
- Cerca di evitare la verifica dello stato interno del tuo SUT - usa la sua API esterna se possibile.
- Cerca di evitare la logica specifica del test nel codice di produzione
- Cerca di evitare l'uso di sottoclassi specifiche del test.
Tutti i punti sopra riportati sono esempi di accoppiamento a scatola bianca utilizzati nei test. Quindi, per evitare completamente i test di rottura del refactoring, utilizzare il test black-box del SUT.
Disclaimer: allo scopo di discutere di refactoring qui, sto usando la parola un po 'più in generale per includere il cambiamento dell'implementazione interna senza effetti esterni visibili. Alcuni puristi potrebbero non essere d'accordo e riferirsi esclusivamente al libro Refactoring di Martin Fowler e Kent Beck, che descrive le operazioni di refactoring atomico.
In pratica, tendiamo a compiere passi non-break leggermente più grandi rispetto alle operazioni atomiche ivi descritte, e in particolare i cambiamenti che lasciano il codice di produzione comportarsi in modo identico dall'esterno potrebbero non lasciare passare i test. Ma penso che sia giusto includere "un algoritmo sostitutivo per un altro algoritmo che ha un comportamento identico" come un refattore, e penso che Fowler sia d'accordo. Lo stesso Martin Fowler afferma che il refactoring può interrompere i test:
Quando scrivi un test di simulazione, stai testando le chiamate in uscita del SUT per assicurarti che parli correttamente con i suoi fornitori. Un test classico si preoccupa solo dello stato finale, non di come lo stato è stato derivato. I test di simulazione sono quindi più associati all'implementazione di un metodo. La modifica della natura delle chiamate ai collaboratori di solito provoca l'interruzione di un test di simulazione.
[...]
L'accoppiamento con l'implementazione interferisce anche con il refactoring, poiché le modifiche all'implementazione hanno maggiori probabilità di superare i test rispetto ai test classici.
Fowler - Le beffe non sono tronconi