Per quanto ho capito, molte persone sembrano concordare sul fatto che i metodi privati non dovrebbero essere testati direttamente, ma piuttosto attraverso qualunque metodo pubblico li chiami. Posso vedere il loro punto, ma ho qualche problema con questo quando cerco di seguire le "Tre leggi del TDD", e utilizzare il ciclo "Red - green - refactor". Penso che sia meglio spiegato da un esempio:
Al momento, ho bisogno di un programma in grado di leggere un file (contenente dati separati da tabulazioni) e filtrare tutte le colonne che contengono dati non numerici. Immagino che probabilmente ci siano già alcuni semplici strumenti per farlo, ma ho deciso di implementarlo da zero, soprattutto perché ho pensato che potesse essere un progetto carino e pulito per me fare pratica con TDD.
Quindi, per prima cosa, "metto il cappello rosso", cioè ho bisogno di un test che fallisca. Ho pensato, avrò bisogno di un metodo che trovi tutti i campi non numerici in una riga. Quindi scrivo un semplice test, ovviamente non riesce a compilare immediatamente, quindi inizio a scrivere la funzione stessa, e dopo un paio di cicli avanti e indietro (rosso / verde) ho una funzione funzionante e un test completo.
Successivamente, continuo con una funzione, "gatherNonNumericColumns" che legge il file, una riga alla volta, e chiama la funzione "findNonNumNumericFields" su ogni riga per raccogliere tutte le colonne che alla fine devono essere rimosse. Un paio di cicli rosso-verdi, e ho finito, avendo di nuovo una funzione funzionante e un test completo.
Ora, immagino che dovrei refactoring. Poiché il mio metodo "findNonNumericFields" è stato progettato solo perché ho pensato che mi sarebbe servito quando si implementava "gatherNonNumericColumns", mi sembra ragionevole lasciare che "findNonNumericFields" diventi privato. Tuttavia, ciò interromperà i miei primi test, dal momento che non avrebbero più accesso al metodo che stavano testando.
Quindi, finisco con un metodo privato e una suite di test che lo testano. Dal momento che così tante persone consigliano che i metodi privati non dovrebbero essere testati, sembra che mi sia dipinta in un angolo qui. Ma dove esattamente ho fallito?
Capisco che avrei potuto iniziare a un livello più alto, scrivendo un test che testerà quello che diventerà il mio metodo pubblico (cioè findAndFilterOutAllNonNumericalColumns), ma che sembra in qualche modo contrario al punto di TDD (almeno secondo Uncle Bob): che dovresti passare continuamente tra test di scrittura e codice di produzione e che in qualsiasi momento, tutti i tuoi test hanno funzionato nell'ultimo minuto o giù di lì. Perché se inizio scrivendo un test per un metodo pubblico, ci saranno diversi minuti (o ore, o persino giorni in casi molto complessi) prima di ottenere tutti i dettagli nei metodi privati per lavorare in modo che il test test il pubblico metodo passa.
Quindi, cosa fare? Il TDD (con il ciclo rapido rosso-verde-refactor) non è semplicemente compatibile con i metodi privati? O c'è un difetto nel mio design?