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


11

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

  • All'inizio di un progetto
  • Lavorando su un MVP / prototipo
  • Aggiunta di funzionalità che non sono completamente definite
  • Lavorando su un progetto su scala ridotta

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

Trovo immensamente più semplice scrivere prima test di integrazione, lavorare sul codice e poi, una volta che l'API è un po 'rafforzata, in realtà lavorare sull'aggiunta di test unitari. I tipi di test che posso eseguire sulla mia mainfunzione, per così dire, e sono più "end to end" di ogni altra cosa.

Questo perché i test unitari sono davvero fastidiosi quando un'API sta cambiando abbastanza rapidamente, come spesso accade quando si lavora su un progetto che soddisfa uno o la maggior parte dei criteri di cui sopra.

Questo approccio è un buon approccio e quali criteri dovrebbero essere presi in considerazione quando si decide se iniziare prima con i test unitari o di integrazione per questi tipi di progetti? Mi manca il valore del test unitario di questo tipo di progetti prima che le API siano più consolidate?


6
Fai quello che funziona meglio per te. Non ascoltare le persone che dicono che devi lavorare in un certo modo per essere efficiente: sai quando sei efficiente e quando non lo sei. Non importa se scrivi prima i test di integrazione o prima i test unitari. Per alcuni progetti in un modo può essere più semplice e per altri in un altro modo. Quello che stai descrivendo potrebbe essere la differenza tra design top-down e bottom-up. Entrambi sono utili, ma il top-down di solito produce progetti migliori.
Frank Hileman,

@FrankHileman in effetti, questo è il mio approccio. Ma dato che sono curioso, voglio assicurarmi di seguire l' approccio giusto nel caso in cui mi manchi qualcosa.
enderland,

Concentrati prima sulle specifiche: le parti non codificate. Quali sono gli invarianti del sistema? Nel fare questo, potresti scoprire che devi prima capire il livello basso o prima il livello alto. Dipende da dove si trovano gli algoritmi più critici o rischiosi. Cerca di toglierli di mezzo prima. Questa è la gestione dei rischi di base.
Frank Hileman,

1
In caso di lavoro sul prototipo, va bene non scrivere test. Lo scopo del prototipo è verificare l'idea di lavoro. L'implementazione del prototipo aiuterà a riconoscere la progettazione prevista dell'applicazione.
Fabio,

Si chiama sviluppo esterno. Potresti voler dare un'occhiata al seguente libro, che fa esattamente questo: amazon.com/dp/0321503627
Eternal21

Risposte:


7

Mi manca il valore del test unitario di questo tipo di progetti prima che le API siano più consolidate?

No. Stai andando bene.

I due grandi obiettivi di TDD sono:

  • Definizione delle interfacce per utilizzo effettivo, anziché per implementazione interna 1
  • Massimizzare la copertura del test

La copertura del test può essere praticamente ottimizzata in entrambi i modi. Cioè, indipendentemente dal fatto che si provino per la prima volta unità piccole , isolate o grandi unità "integrate", è possibile scrivere i test prima delle implementazioni.

Quello che si guadagna per iscritto di più alto livello ( "integrazione") mette alla prova prima, come si sta facendo, è la garanzia che le interfacce di livello superiore e le interazioni sono anche definita in primo luogo in base al loro utilizzo, piuttosto che con le loro implementazioni interne.

Lo stesso effetto può essere ampiamente ottenuto con una buona "architettura" e diagrammi. Ma quei test di alto livello possono spesso rivelare cose che hai perso nei tuoi diagrammi o che hai appena sbagliato nel tuo lavoro di "architettura".


Se non stai effettivamente facendo TDD (o qualcosa del genere), l'ordine in cui scrivi i test non ha molta importanza. Le interfacce esistono già al momento del test, quindi è molto meno probabile che i test cambino qualsiasi cosa - serviranno solo a proteggere da particolari cambiamenti di rottura.

Ma, se ti preoccupi di costruire l'implementazione top-down 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 è alla loro mercé ...


1. Questo vale anche se non stai eseguendo un TDD completo. Anche se stai solo scrivendo 1 o 2 test prima dell'implementazione, questi 1 o 2 test possono aiutarti a definire o perfezionare le tue interfacce prima che sia troppo tardi!


1

Ho lavorato nel modo in cui lavori. E non ti dirò che non puoi. Ti avvertirò di qualcosa in cui potresti imbatterti.

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 semplice scrivere i tipi di test che rendono il refactoring più difficile. Questo tende a perdere il controllo fino a quando non perdi tutta la fiducia nel TDD.

Tuttavia, stai già lavorando a qualcosa. Non ti dirò di smettere. Dirò che varrebbe la pena iniziare qualcos'altro che hai il tempo di esplorare e seguire il ciclo del refattore verde rosso dall'inizio. Assicurati di utilizzare effettivamente i test per aiutarti a refactoring. Fino a quando 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 ciò

Trovo immensamente più semplice scrivere prima i test di integrazione, lavorare sul codice e poi, una volta che l'API è un po 'rafforzata, in realtà lavorare sull'aggiunta di test unitari. I tipi di test che posso eseguire sulla mia funzione principale, per così dire, e sono più "end to end" di ogni altra cosa.

Comprendi che un unit test NON è semplicemente un test che agisce su una classe. Fintanto che l'API su cui stai lavorando può essere testata senza eseguire alcuna delle seguenti operazioni, stai testando bene l'unità:

  • Parla con il database
  • Comunica attraverso la rete
  • Tocca il file system
  • Non può essere eseguito contemporaneamente a tutti gli altri test unitari
  • Devi fare cose speciali per il tuo ambiente (come la modifica dei file di configurazione) per eseguirlo.

Michael Feathers: un insieme di regole per i test unitari

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

Proprio come i metodi privati ​​non devono più essere testati, quindi vengono testati testando i metodi pubblici che li utilizzano, gli oggetti non devono essere inizialmente sviluppati con il proprio cablaggio di test. Solo quando gli oggetti vengono considerati per l'uso indipendente dalla storia end-to-end, devono davvero essere trattati come se avessero una propria interfaccia e un comportamento per confermare. Se stai attento a questo è quando rendi pubblici quegli oggetti. In questo modo non fai promesse che non hai testato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.