Quanti test per metodo?
Bene il massimo teorico e molto poco pratico è la complessità N-Path (si presuma che i test coprano tutti modi diversi attraverso il codice;)). Il minimo è UNO!. Per metodo pubblico che non esegue il test dei dettagli di implementazione, ma solo i comportamenti esterni di una classe (restituisce valori e chiama altri oggetti).
Citi:
*And the thought of testing each of your methods with its own test method (in a 1-1 relationship) will be laughable. *
e poi chiedi:
So if creating a test for each method is 'laughable', how/when do you chose what you write tests for?
Ma penso che tu abbia frainteso l'autore qui:
L'idea di avere one test method
per one method in the class to test
è ciò che l'autore chiama "ridicolo".
(Per me almeno) Non si tratta di "meno", si tratta di "altro"
Quindi fammi riformulare come ho capito:
E il pensiero di testare ciascuno dei tuoi metodi con SOLO UN METODO (il suo metodo di test in una relazione 1-1) sarà ridicolo.
Per citare di nuovo il tuo preventivo:
When you realize that it's all about specifying behaviour and not writing tests, your point of view shifts.
Quando pratichi TDD, non pensare :
Ho un metodo calculateX($a, $b);
e ha bisogno di un test testCalculcateX
che verifica TUTTO il metodo.
Ciò che TDD ti dice è di pensare a cosa dovrebbe fare il tuo codice :
Ho bisogno di calcolare il più grande dei due valori ( primo caso di test! ) ma se $ a è minore di zero, allora dovrebbe produrre un errore ( secondo test case! ) e se $ b è minore di zero dovrebbe .... ( terzo test case ) e così via.
Vuoi testare i comportamenti, non solo i singoli metodi senza contesto.
In questo modo si ottiene una suite di test che è la documentazione per il proprio codice e REALMENTE spiega cosa si prevede di fare, forse anche perché:)
Come decidi quale parte del codice crei per i test unitari?
Bene, tutto ciò che finisce nel repository o ovunque vicino alla produzione richiede un test. Non penso che l'autore delle tue citazioni non sarebbe d'accordo con quello come ho cercato di affermare in precedenza.
Se non hai un test per questo, diventa molto più difficile (più costoso) cambiare il codice, specialmente se non stai facendo il resto.
TDD è un modo per assicurarti di avere i test per TUTTO, ma finché scrivi i test va bene. Di solito li scrivendo nello stesso giorno aiuta dal momento che non lo farai più tardi, vero? :)
Risposta ai commenti:
a decent amount of methods can't be tested within a particular context because they either depend or are dependent upon other methods
Bene, ci sono tre cose che questi metodi possono chiamare:
Metodi pubblici di altre classi
Possiamo prendere in giro altre classi così abbiamo definito lo stato lì. Abbiamo il controllo del contesto, quindi non è un problema lì.
* Metodi protetti o privati sullo stesso *
Qualsiasi cosa che non fa parte dell'API pubblica di una classe non viene testata direttamente, di solito.
Vuoi testare il comportamento e non l'implementazione e se una classe fa tutto il suo lavoro in un grande metodo pubblico o in molti più piccoli metodi protetti che vengono chiamati è implementazione . Vuoi essere in grado di CAMBIARE quei metodi protetti SENZA toccare i test. Perché i tuoi test si interromperanno se il tuo codice cambia comportamento! Ecco a cosa servono i tuoi test, per dirti quando rompi qualcosa:)
Metodi pubblici sulla stessa classe
Questo non succede molto spesso, vero? E se lo fa nel seguente esempio ci sono alcuni modi per gestirlo:
$stuff = new Stuff();
$stuff->setBla(12);
$stuff->setFoo(14);
$stuff->execute();
Che i setter esistono e non fanno parte della firma del metodo execute è un altro argomento;)
Quello che possiamo testare qui è se gli executes esplodono quando impostiamo i valori sbagliati. Quella setBla
genera un'eccezione quando si passa una stringa può essere testata separatamente, ma se vogliamo testare che quei due valori consentiti (12 e 14) non funzionano INSIEME (per qualsiasi motivo) di quello che è un caso di test.
Se vuoi una "buona" suite di test puoi, in PHP, magari (!) aggiungere un'annotazione @covers Stuff::execute
per assicurarti di generare solo la copertura del codice per questo metodo e l'altra roba che è appena impostata deve essere testato separatamente (di nuovo, se lo vuoi).
Quindi il punto è: Forse devi prima creare un po 'del mondo circostante, ma dovresti essere in grado di scrivere casi di test significativi che di solito occupano solo una o forse due funzioni reali (i setter don' conta qui). Il resto può essere deriso via etere o essere prima testato e poi invocato (vedi @depends
)
* Nota: la domanda è stata migrata da SO e inizialmente riguardava PHP / PHPUnit, questo è il motivo per cui il codice di esempio ei riferimenti provengono dal mondo php, penso che questo sia applicabile anche ad altre lingue in quanto phpunit non differisce molto da altri framework di testing xUnit.