Prospettiva:
Quindi facciamo un passo indietro e chiediamo che TDD sta cercando di aiutarci. TDD sta cercando di aiutarci a determinare se il nostro codice è corretto o meno. E per corretto intendo "il codice soddisfa i requisiti aziendali?" Il punto di forza è che sappiamo che saranno necessarie modifiche in futuro e vogliamo assicurarci che il nostro codice rimanga corretto dopo aver apportato tali modifiche.
Ho sollevato questa prospettiva perché penso che sia facile perdersi nei dettagli e perdere di vista ciò che stiamo cercando di ottenere.
Principi - SAP:
Anche se non sono un esperto di TDD, penso che manchi parte di ciò che il principio dell'asserzione singola (SAP) sta cercando di insegnare. SAP può essere riformulato come "testare una cosa alla volta". Ma TOTAT non è facile come SAP.
Testare una cosa alla volta significa che ti concentri su un caso; un percorso; una condizione al contorno; un caso di errore; uno qualunque per test. E l'idea alla base di ciò è che devi sapere cosa si è rotto quando il test case fallisce, in modo da poter risolvere il problema più rapidamente. Se si verificano più condizioni (ad es. Più di una cosa) all'interno di un test e il test fallisce, allora si ha molto più lavoro da fare. Devi prima identificare quale dei casi multipli ha avuto esito negativo e quindi capire perché quel caso non è riuscito.
Se si verifica una cosa alla volta, l'ambito di ricerca è molto più piccolo e il difetto viene identificato più rapidamente. Tieni presente che "testare una cosa alla volta" non ti esclude necessariamente dal guardare più di un output di processo alla volta. Ad esempio, quando collaudo un "percorso noto noto", potrei aspettarmi di vedere un valore risultante specifico foo
e un altro valore in bar
e posso verificarlo foo != bar
come parte del mio test. La chiave è raggruppare logicamente i controlli di output in base al caso in esame.
Principi - PMP:
Allo stesso modo, penso che ti manchi un po 'di ciò che il metodo del metodo privato (PMP) deve insegnarci. PMP ci incoraggia a trattare il sistema come una scatola nera. Per un dato input, dovresti ottenere un determinato output. Non ti interessa come la scatola nera genera l'output. Ti interessa solo che le tue uscite siano allineate con i tuoi input.
PMP è davvero una buona prospettiva per esaminare gli aspetti API del tuo codice. Può anche aiutarti a valutare ciò che devi testare. Identifica i tuoi punti di interfaccia e verifica che soddisfino i termini dei loro contratti. Non devi preoccuparti di come i metodi dietro l'interfaccia (aka privati) fanno il loro lavoro. Devi solo verificare che abbiano fatto quello che dovevano fare.
TDD applicato ( per te )
Quindi la tua situazione presenta un po 'di rughe oltre un'applicazione ordinaria. I metodi della tua app sono statiful, quindi il loro output dipende non solo dall'input ma anche da ciò che è stato fatto in precedenza. Sono sicuro che dovrei <insert some lecture>
qui che lo stato è orribile e bla bla bla, ma questo non aiuta davvero a risolvere il tuo problema.
Presumo che tu abbia una sorta di tabella del diagramma di stato che mostra i vari stati potenziali e cosa bisogna fare per innescare una transizione. In caso contrario, ne avrai bisogno in quanto aiuterà a esprimere i requisiti aziendali per questo sistema.
I test: in primo luogo, si finirà con una serie di test che attuano il cambiamento di stato. Idealmente, avrai test che esercitano l'intera gamma di cambiamenti di stato che possono verificarsi, ma posso vedere alcuni scenari in cui potresti non aver bisogno di andare fino in fondo.
Successivamente, è necessario creare test per convalidare l'elaborazione dei dati. Alcuni di questi test di stato verranno riutilizzati quando si creano i test di elaborazione dei dati. Ad esempio, supponiamo di avere un metodo Foo()
con output diversi basato su an Init
e State1
stati. Ti consigliamo di utilizzare il ChangeFooToState1
test come fase di installazione per testare l'output quando " Foo()
è in State1
".
Ci sono alcune implicazioni dietro quell'approccio che voglio menzionare. Spoiler, questo è dove farò infuriare i puristi
Prima di tutto, devi accettare che stai usando qualcosa come test in una situazione e una configurazione in un'altra situazione. Da un lato, questa sembra essere una violazione diretta di SAP. Ma se logicamente hai ChangeFooToState1
due scopi, allora stai ancora incontrando lo spirito di ciò che SAP ci sta insegnando. Quando è necessario accertarsi che gli Foo()
stati delle modifiche vengano utilizzati ChangeFooToState1
come test. E quando è necessario convalidare " Foo()
l'output in State1
", si utilizza ChangeFooToState1
come impostazione.
Il secondo elemento è che da un punto di vista pratico, non vorrai test di unità completamente randomizzati per il tuo sistema. È necessario eseguire tutti i test di modifica dello stato prima di eseguire i test di convalida dell'output. SAP è una specie del principio guida dietro quell'ordinamento. Per affermare ciò che dovrebbe essere ovvio, non è possibile utilizzare qualcosa come impostazione se non riesce come test.
Mettendolo insieme:
Usando il diagramma di stato, genererai test per coprire le transizioni. Ancora una volta, usando il diagramma, si generano test per coprire tutti i casi di elaborazione dei dati di input / output guidati dallo stato.
Se segui questo approccio, i bloated, complicated, long, and difficult to write
test dovrebbero essere un po 'più facili da gestire. In generale, dovrebbero finire più piccoli e dovrebbero essere più concisi (cioè meno complicati). Dovresti notare che i test sono anche più disaccoppiati o modulari.
Ora, non sto dicendo che il processo sarà completamente indolore perché scrivere buoni test richiede un certo sforzo. E alcuni saranno ancora difficili perché stai mappando un secondo parametro (stato) su alcuni dei tuoi casi. E a parte questo, dovrebbe essere un po 'più evidente il motivo per cui un sistema senza stato è un metodo più facile da costruire per i test. Ma se adattate questo approccio alla vostra applicazione, dovreste scoprire che siete in grado di dimostrare che l'applicazione funziona correttamente.