Valutare se scrivere test di unità o di integrazione prima su progetti blue-sky / prototype

8

Qualcosa che ho notato di recente è quando sto facendo i seguenti tipi di progetti:

  • All'inizio di un progetto
  • Lavorare su un MVP / prototipo
  • Aggiunta di funzioni che non sono completamente definite
  • Lavorare su un progetto su scala ridotta

Per riferimento, sto lavorando ad un progetto Python che attualmente ha ~ 1k linee di codice, inclusi alcuni commenti e tutti gli spazi bianchi.

Trovo immensamente più facile scrivere per primi test di integrazione, lavorare sul codice e quindi una volta che l'API è in qualche modo rafforzata, in realtà funziona sull'aggiunta dei test unitari. I tipi di test che posso eseguire sulla mia funzione main , per così dire, sono più "end to end" di qualsiasi altra cosa.

Questo perché i test unitari sono davvero fastidiosi quando un'API sta cambiando abbastanza rapidamente, il che spesso accade quando si lavora su un progetto che corrisponde a una o più delle seguenti condizioni.

Questo approccio è un buon approccio e quali criteri dovrebbero essere presi in considerazione quando si decide se iniziare con test di unità o integrazione prima per questi tipi di progetti? Mi manca il valore dell'unità testare questi tipi di progetti prima che le API siano più solide?

    
posta enderland 07.04.2017 - 19:40
fonte

2 risposte

5

Am I missing the value of unit testing these sorts of projects before the APIs are more solidified?

No. Stai andando bene.

I due grandi obiettivi di TDD sono:

  • Definizione di interfacce per uso effettivo, piuttosto che per implementazione interna 1
  • Massimizzazione della copertura del test

La copertura del test può essere alquanto ottimizzata in entrambi i casi. Cioè, indipendentemente dal fatto che test prima piccole , unità isolate o grandi , unità "integrate", hai la possibilità di scrivere i tuoi test prima delle implementazioni.

Ciò che guadagni scrivendo i test di livello superiore ("integrazione") prima, come stai facendo, è la certezza che le tue interazioni e interazioni di livello superiore sono anche definite principalmente in base al loro uso, piuttosto che dalle loro implementazioni interne.

Lo stesso effetto può essere largamente raggiunto con alcuni buoni "architetti" e diagrammi. Tuttavia, questi test di alto livello possono spesso rivelare cose che mancavano nei tuoi diagrammi o che hai appena sbagliato nel tuo lavoro di "architettura".

Se in realtà non stai facendo TDD (o qualcosa del genere), l'ordine in cui scrivi i test non conta molto. Le interfacce esistono già dal momento in cui esegui il test, quindi è molto meno probabile che i tuoi test cambieranno qualsiasi cosa - saranno solo serviti per proteggere da particolari cambiamenti di interruzione.

Ma, se sei preoccupato di costruire l'implementazione dall'alto verso il basso contro buttom-up, il primo punto elenco si applica ancora in larga misura. Il codice di alto livello aiuta a definire interfacce di basso livello. Considerando che, se le interfacce di basso livello sono scritte per prime (o altrimenti esistono già), il codice di alto livello è nella loro misericordia ...

1. Questo si applica anche se non stai facendo un TDD completo. Anche se stai solo scrivendo 1 o 2 test prima della tua implementazione, questi 1 o 2 test possono aiutarti a definire o perfezionare le tue interfacce prima che sia troppo tardi!

    
risposta data 07.04.2017 - 20:43
fonte
1

Ho lavorato nel modo in cui lavori. E non ho intenzione di dirti che non puoi. Ti avvertirò su qualcosa che puoi incontrare.

Quando ogni unit test è semplicemente un retrofit, è difficile imparare a renderli flessibili. Tendono ad essere nient'altro che test di regressione. Dal momento che non li hai mai usati per aiutarti a refactoring è molto facile scrivere i tipi di test che rendono più difficile il refactoring. Questo tende a perdere il controllo fino a perdere ogni fiducia in TDD.

Tuttavia, stai già lavorando a qualcosa. Non ho intenzione di dirti di smettere. Dirò che potrebbe valere la pena iniziare da qualcos'altro che hai il tempo di esplorare e seguire il ciclo del refact rosso verde dall'inizio. Assicurati di utilizzare effettivamente i test per aiutarti a refactoring. Finché non avrai imparato questo modo di lavorare usalo con parsimonia su qualcosa che conta. Questo è un modo molto diverso di codificare e ci si abitua. Farlo a metà strada non farà bene a nessuno.

Detto questo

I find it immensely easier to first write integration tests, work on the code, and then once it the API is somewhat hardened actually work on adding unit tests. The types of tests that I can run on my main function, so to speak, and are more "end to end" than anything else.

Comprendi che un test unitario NON è semplicemente un test che agisce su una classe. Finché l'API su cui stai lavorando può essere testata senza eseguendo una delle seguenti azioni, fai dei test unitari bene:

  • It talks to the database
  • It communicates across the network
  • It touches the file system
  • It can't run at the same time as any of your other unit tests
  • You have to do special things to your environment (such as editing config files) to run it.

Michael Feathers: A Set of Unit Testing Rules

Quindi se il tuo test end-to-end coinvolge più di un oggetto va bene. Questo è un test unitario e non un test sugli oggetti.

Proprio come i metodi privati non hanno bisogno di essere testati più di quanto non vengano testati attraverso test dei metodi pubblici che li usano, gli oggetti non devono essere inizialmente sviluppati sotto il loro cablaggio di test. Solo quando gli oggetti vengono presi in considerazione per essere utilizzati indipendentemente dalla storia end-to-end, devono essere trattati come se avessero un'interfaccia e un comportamento da confermare. Se stai attento a ciò, rendi pubblici questi oggetti. In questo modo non fai promesse che non hai testato.

    
risposta data 01.11.2017 - 14:31
fonte

Leggi altre domande sui tag