I test che passano direttamente dall'inizio si verificano in genere quando si implementa qualcosa in un modo più generale di quello effettivamente necessario per i test in corso. Questo è abbastanza normale : i test di unità possono fornire solo un numero limitato e limitato di valori di input per una determinata funzione, ma la maggior parte delle funzioni è scritta per un ampio intervallo di valori di input possibili. Spesso un'implementazione progettata specificamente per i test case attuali sarebbe più complicata di una soluzione più generale. In questo caso, sarebbe ingombrante e soggetto a errori progettare artificialmente il codice in modo da funzionare solo per i casi di test e fallire per tutto il resto.
Ad esempio, diciamo che è necessaria una funzione per restituire il minimo di alcuni valori da un determinato array. Hai realizzato un'implementazione, guidata da un test con un array contenente solo uno o due valori. Ma invece di implementarlo in modo contorto eseguendo il confronto su diversi elementi (forse solo i primi due elementi), si chiama una funzione di minimo dell'array dalla libreria standard del proprio ecosistema linguistico e quindi si rende l'implementazione un unico elemento . Quando decidi di aggiungere un test con un array di cinque elementi, il test probabilmente passerà dall'inizio.
Ma come fai a sapere che il test non è "verde" a causa di un bug nel test stesso? Un modo semplice e diretto per avvicinarsi a questo è apportare una modifica temporanea all'oggetto sotto test per fare fallire il test. Ad esempio, potresti aggiungere intenzionalmente una riga if (array.size()==5) return 123
alla tua funzione. Ora il tuo test a cinque elementi fallirà, quindi sai
- il test viene eseguito
- la chiamata Assert nel test viene eseguita
- la chiamata Assert nel test convalida la cosa giusta
che dovrebbe darti una certa sicurezza nel test. Dopo aver visto il test fallire, annullare la modifica e il test dovrebbe passare di nuovo.
In alternativa, puoi modificare il risultato previsto di un test: diciamo che il tuo test di passaggio contiene un'asserzione come
int result = Subject.UnderTest(...);
Assert.AreEqual(1,result);
quindi puoi modificare il test e sostituire "1" con "2". Quando il test fallisce (come previsto), sai che funziona come dovrebbe, e puoi annullare la sostituzione e vedere se il test diventa ora verde. Il rischio di introdurre un bug nel test con questo tipo di sostituzione è molto piccolo, quindi questo è probabilmente accettabile per la maggior parte dei casi reali.
Un modo diverso, forse discutibile, è di impostare un punto di interruzione nel test e utilizzare un debugger per eseguirlo. Ciò dovrebbe anche darti una certa sicurezza che il codice di prova sia effettivamente eseguito, e ti dà la possibilità di convalidare il percorso attraverso il test attraverso un'ispezione passo-passo. Tuttavia, si deve fare molta attenzione a non trascurare gli errori in un percorso di codice in modo specifico per un test in errore. Per test complessi, puoi prendere in considerazione l'idea di fare entrambe le cose - rendendo artificialmente e un debugger per controllarlo.