TDD solo in teoria

29

Un po 'più di un anno fa ho avuto la fortuna di essere in grado di prendermi una pausa di 9 mesi dal lavoro. Ho deciso che in quel momento avrei perfezionato le mie abilità in C #. Ho iniziato a lavorare su un gruppo di progetti e mi sono imposto di seguire TDD.

È stato un processo abbastanza illuminante.

All'inizio è stato difficile, ma nel tempo ho imparato a scrivere più codice testabile (che, a quanto risulta, tende ad essere più codice SOLID) e nel processo ho anche affinato le mie capacità di progettazione OO.

Ora sono di nuovo nel mondo del lavoro e sto notando qualcosa di strano.

Preferisco non seguire TDD.

Trovo che TDD mi rallenti e in effetti rende più difficile progettare un'applicazione pulita.

Invece, ho adottato un approccio leggermente (massivamente) diverso:

  1. Scegli una porzione verticale di lavoro
  2. Sviluppa un prototipo funzionante
  3. Refactor fino a quando tutto è bello e ordinato
  4. Siediti e apprezza il codice splendidamente SOLID e verificabile che ho scritto.

Potresti aver notato che il passaggio 1 non era "definire la superficie pubblica del mio target di test" e il passaggio 2 non era "testare i bejesus fuori da detta superficie pubblica". Potresti aver anche notato che nessuno dei passaggi richiede test. Sto scrivendo un codice verificabile, ma non lo sto ancora testando ... ancora.

Ora vorrei chiarire che in realtà non ho rinunciato a nessun tipo di test. Il codice che sto scrivendo funziona . Funziona perché lo sto testando manualmente.

Vorrei anche chiarire che non ho rinunciato a tutti i test automatici. Questo è dove il mio processo è diverso. Ed è per questo che sto facendo questa domanda.

TDD in teoria. Non in pratica.

Il mio processo si è evoluto un po 'e ho trovato un equilibrio tra TDD e nessun test che trovo molto produttivo e anche ragionevolmente sicuro. Va come segue:

  1. Implementa una fetta di lavoro verticale funzionante con i test in mente, ma non scrivere test.
  2. Se in fondo alla strada (ad esempio, un mese più tardi) tale sezione deve essere modificata
    1. Scrivi test di unità, test di integrazione, test di comportamento, ecc. che garantiscano che la parte di lavoro sia corretta
    2. Modifica il codice
  3. Se quella fetta non ha bisogno di modifiche,
    1. Non fare nulla

Spostando semplicemente l'onere di scrivere i test prima di scrivere il codice prima di modificare il codice sono stato in grado di produrre molto più codice funzionante. E quando riesco a scrivere test, ne scrivo molti meno, ma copro quasi il terreno (un ROI più alto).

Mi piace questo processo, ma temo che potrebbe non adattarsi bene. Il suo successo dipende dal fatto che gli sviluppatori siano diligenti nello scrivere test prima di cambiare le cose. E questo sembra un grosso rischio. Ma, TDD ha lo stesso rischio.

Quindi, vado all'inferno [BT] DD o è una forma comune di codifica e test pragmatici?

Mi piacerebbe continuare a lavorare in questo modo. Cosa posso fare per rendere questo processo funzionante a lungo termine?

Nota:

Sono l'unico sviluppatore dei miei progetti e sono responsabile di tutto: raccolta dei requisiti, progettazione, architettura, test, implementazione, ecc. Sospetto che questo sia il motivo per cui il mio processo funziona.

    
posta MetaFight 04.06.2015 - 18:36
fonte

9 risposte

6

Per far funzionare il processo a lungo termine, scriverò i test quando il codice è in fase di scrittura.

Che può sembrare contraddire il tuo approccio. Comunque hai posto la domanda quindi ti darò la mia opinione:

Non è necessario scrivere i test prima del codice. dimentica quella purezza. Comunque vuoi scrivere i test intorno a in quel momento.
Una volta ottenuto il funzionamento del codice, l'hai modificato leggermente, ottenuto alcuni bug (stiamo parlando di un lasso di tempo qui), sei quindi in un punto di massima conoscenza di ciò che sta facendo il codice. Questo è un ottimo momento per scrivere test che catturano le tue conoscenze.

Lasciare questo fino a più tardi significa che la conoscenza diminuirà (naturalmente) nel tempo.

Significa anche che se dovessi andartene e se qualcun altro dovesse subentrarti non avrai il debito tecnico immediato di non aver documentato (attraverso test) cosa fa cosa.

Soprattutto, "un giorno" potrebbe non venire. Potresti essere colpito da un autobus o salire sull'autobus per nuove avventure.

Infine, i test manuali non si ridimensionano e spesso non coprono tutti i dispositivi utilizzati dall'utente finale.

    
risposta data 10.06.2015 - 11:57
fonte
9

Sebbene TDD sia difficile da implementare al 100%, c'è un difetto nel tuo approccio

  1. Implementa una fetta di lavoro verticale funzionante

    1.1 trascorrono 1 anno ....

    1.2 Un nuovo dev inizia a lavorare sul progetto

  2. Se quella sezione ha bisogno di modifiche

    2.3 Parametri e nomi dei metodi in stile 'Pulisci codifica' 'GetUnicorn (colourOfUnicorn)'

    2.4 Leggi i commenti xml 'Ottiene un unicorno d'oro (per andare in bicicletta) (obvs)'

    2.5 Cerca lo sviluppo originale

    2.6 Spero che ricordino ciò che il codice dovrebbe fare

    2.7 Fai in modo che spieghino tutto

  3. Scrivi test di unità, test di integrazione, test di comportamento, ecc speriamo che la porzione di lavoro sia corretta

  4. Modifica il codice

Penso che tu abbia ragione nell'identificare che i test di unità mostrano realmente il loro valore quando sono richieste modifiche.

    
risposta data 04.06.2015 - 18:58
fonte
4

Sono d'accordo sia con Daniel Hollinrake che con Ewan, che il primo punto chiave per cui il test-only-if-modify funziona bene finora è:

I am the sole developer on my projects and I am responsible for everything

e che un probabile secondo punto chiave è:

you're producing nice clean code

Non credo che TDD apporti un enorme aumento di produttività per i programmatori unici, e potrebbe non migliorare enormemente la qualità del tuo codice se stai già scrivendo un buon codice pulito.

Tuttavia, TDD migliorerà sicuramente la qualità del codice di programmatori poveri / inesperti / obsoleti, specialmente quando sarà il momento di modificare il codice senza rompere nient'altro. E ancora di più se la persona che modifica il codice non è la stessa persona che ha scritto il codice in origine o diversi mesi sono passati in mezzo.

In altre parole, penso che TDD sia una buona pratica per migliorare la qualità del tuo codice (come riconosci te stesso) ma anche (e più importante) una sorta di copertura quando lavori con programmatori mediocri o mediocri (per esempio, da un reparto diverso o una società diversa), che è una situazione molto più comune rispetto al lavoro da solo.

    
risposta data 10.06.2015 - 13:55
fonte
3

Per me la cosa fondamentale sembra essere questa:

I am the sole developer on my projects and I am responsible for everything: Requirements gathering, design, architecture, testing, deployment, etc. I suspect this is why my process is working.

Questo funziona per te e stai producendo un bel codice pulito (presumo!). L'unica cosa che direi che devi fare è creare un harness di test in modo che altri sviluppatori possano entrare e avere fiducia nelle modifiche. Anche il cablaggio di test assicura coerenza nel comportamento del codice.

Penso che il tuo approccio sia simile al mio. Di solito sono l'unico sviluppatore sui miei progetti. Ho scoperto che l'apprezzamento di TDD mi ha permesso di scrivere funzioni più piccole e un codice più pulito, ma aggiungo dei test mentre scrivo il codice come un'imbracatura di prova. In questo modo, man mano che il codice si evolve e le funzionalità cambiano, posso essere ragionevolmente sicuro di apportare modifiche.

Un motivo secondario per scrivere i test è che ritengo che siano una forma di documentazione. Possono spiegare i miei ragionamenti sul perché è stata creata una funzione. Ma qui, sto pensando di più su Behavior Driven Development.

    
risposta data 10.06.2015 - 11:22
fonte
3

I test unitari riguardano il problema del mantenimento del codice. Mentre ci sono persone che dicono che sono più veloci a scrivere codice con TDD piuttosto che senza, non sono sorpreso che tu sia in grado di scrivere più codice nuovo senza scrivere test.

I problemi che riesco a vedere con la pratica di scrivere test appena prima di cambiarlo:

Spesso ho bisogno di apportare modifiche in fretta

Anche se potresti risparmiare tempo complessivo solo scrivendo test quando ne hai bisogno, non tutto il tempo è uguale. Trascorrere 2 ore a scrivere test per risparmiare 1 ora quando sono in modalità di crisi - ne vale la pena.

È più facile scrivere test contemporaneamente mentre scrivo il codice

Per scrivere correttamente i test unitari è necessario comprendere il codice che sto testando. Uso spesso il test delle unità come esercizio di comprensione, ma il test di unità esistente può richiedere molto tempo perché la comprensione del codice esistente richiede molto tempo. Confrontalo per scrivere i test mentre scrivi il codice e lo troverai molto più veloce perché hai già capito il codice - l'hai appena scritto!

La definizione di Michael Feathers del codice legacy è codice senza test. Indipendentemente dal fatto che tu sia d'accordo con la sua definizione, è chiaro che una parte considerevole del costo di modifica del codice esistente si sta assicurando che funzioni ancora come previsto, spesso non è nemmeno chiaro quale sia il comportamento previsto.

L'unità di scrittura verifica gli offset che costano codificando la comprensione di quale sia il comportamento corretto, oltre a fornire un modo semplice per "noi futuri" per verificare che il comportamento sia ancora corretto.

    
risposta data 01.07.2017 - 17:48
fonte
2

Questa è una buona domanda, e FWIW ti lancerò i miei due centesimi.

Circa un anno fa stavo codificando in Salesforce, una piattaforma che aveva un meccanismo radicato che ti costringeva a non scrivere necessariamente i test prima di codificare , ma ti costringeva piuttosto a scrivere test in generale.

Il modo in cui ha funzionato è che il sistema ti costringerebbe a scrivere test e farebbe un calcolo del numero di righe del tuo codice che sono state testate in una percentuale. Se tutto il codice durante l'istanza di produzione è sceso sotto il 75% testato. Salesforce non ha più lavoro.

Il risultato finale era che ogni volta che facevi qualcosa in Salesforce dovevi scrivere o aggiornare i test. Mentre sono sicuro che questo ha un enorme impatto sulla quota di mercato di Salesforce, in termini di vita dello sviluppatore è stato un enorme dolore nel culo .

Molto tempo stavi solo cercando di superare un piccolo ticket, quindi i test arrivano e raddoppiano i tempi di sviluppo, per una funzionalità che sai funziona.

Quindi il concetto imbarazzante di TDD ha attraversato il nostro dipartimento, fino ai nostri database. I nostri architetti hanno voluto sottoporre a test approfonditi tutti gli aspetti del nostro reparto IT. Leggero dolore al culo, incontra ancora più dolore nel sedere.

Allora il TDD non aveva mai avuto senso per me, e anche ora non lo è ancora. Molte delle funzionalità che ho scritto nel mio ruolo attuale si svolgono in un meccanismo simile a quello che hai menzionato: in sezioni verticali che perfeziono finché non funzionano. Quando ero in quel vecchio ruolo, e ancora adesso spesso non so cosa il mio codice farà fino a quando non lo scrivo , quindi l'idea che posso scrivere test per guidare il codice I scriverò solo .. non ha senso per me, è ingombrante e per lo più una perdita di tempo.

Tutto ciò detto, i test sono cose meravigliose e magiche che rendono tutto giusto nel mondo . Rendono il tuo codice corretto, assicurano che la tua app esegua ciò che pensi che faccia, e in generale tutto liscio. La domanda quindi non è se si scrivono i test prima di codificare, o dopo la codifica, la domanda è quanto tempo hai intenzione di impegnarsi a testare. Questo è il vero problema, almeno nella mia esperienza di sviluppo del software. I test richiedono tempo e denaro e devi farlo nel quadro di interessi in competizione.

E così, in generale, sono d'accordo con te: il TDD in pratica è un po 'scomodo e ingombrante. A quel punto devi tenere a mente ciò che funziona meglio nella tua situazione attuale . Se stai scrivendo codice critico, assicurati che sia testato in generale. Se hai tempo da dedicare a TDD, prova a vedere se aggiunge qualcosa al processo.

    
risposta data 06.06.2015 - 03:07
fonte
1

Non potrei raccomandare il tuo approccio.

Se utilizzo il tuo approccio, sarebbe ad esempio il seguente (la casa è l'applicazione):

  1. Inizio a costruire una casa per la mia famiglia come muratore con qualche conoscenza o come principiante.
  2. Conosco i requisiti come le stanze dei bambini, la stanza degli ospiti e inizio a costruire la mia casa "prototipo".
  3. Più di un paio di volte dopo la tua casa "prototipo" è terminata.
  4. Inizio a cercare se la struttura è sufficientemente stabile manualmente. Quindi raccolgo un sacco di pesi e lo porto nelle diverse stanze del primo piano. Per essere sicuro che quando mi siedo in una stanza con la mia famiglia il soffitto non si rompa. Ma si rompe e comincio a refactoring. Prima pulisci tutta la massa. Costruiscilo di nuovo e testalo di nuovo manualmente finché non è abbastanza stabile.
  5. Poi mi trasferisco con la mia famiglia. Tutto va bene.
  6. Una falena più tardi i miei cugini e genitori stanno venendo a trovarci. Ma prima che possano entrare nella nostra casa hanno bisogno di pagare un architetto e un ingegnere civile per assicurarsi che il soffitto non si rompa quando ci sediamo in una delle stanze del primo piano.
  7. L'architetto e l'ingegnere civile hanno molto lavoro perché non hanno niente da cui cominciare. Quindi hanno bisogno di andare a casa mia e vedere come lo costruisco.
  8. E di nuovo non è abbastanza stabile. Quindi devono refactoring il terreno del primo piano.
  9. Ma dopo tutto va tutto bene e tutti possono tranquillamente entrare nella mia casa.

Quindi il tuo approccio richiede molto tempo e tanta conoscenza prima di costruire la casa con il tuo approccio. O ci vuole un sacco di tempo! Inoltre, non è carino per Gentleman lasciare altri test di scrittura per il tuo codice quando i requisiti sono cambiati.

Quindi esiste un approccio migliore senza programmare un "prototipo" e avviare il refactoring. Invece di programmare un prototipo "crea un design con UML della tua applicazione come segue.

  1. Crea un diagramma di UseCase. Puoi utilizzare draw.io per iniziare.
  2. Di creare un diagramma EPK basato sul tuo UseCases per determinare il comportamento. (COMPORTAMENTO della tua applicazione) Più veloce al refactor che refactoring un prototipo codificato. Soprattutto quando sei un principiante.
  3. Crea un diagramma di classe. (STRUTTURA della tua applicazione)
  4. Determina dove potresti avere problemi nell'implementazione del comportamento.
  5. Scrivi per questo un semplice prototipo con forse 10 o 20 righe di codice per determinare come implementare questo comportamento. Buono per principianti. Oppure guarda un tutorial, guarda il codice sorgente di altre applicazioni di esempio là fuori. Come l'hanno risolto.
  6. Poi inizia la codifica. Pugno i test di successo del tuo UseCase. Questo può essere fatto in diversi modi. Prima crea tutta la Struttura necessaria per il test e quella UseCase. Quando usi Enterprise Architekt puoi creare la struttura per te. Basato sui tuoi diagrammi. O creare la struttura mentre si collega il test. Quindi non compaiono errori di compilazione. La menzione qui è che devi SOLO testare il COMPORTAMENTO della tua applicazione. I UseCase che hai.
  7. Di implementa il comportamento del tuo UseCase.
  8. Dopo il successo, UseCases inizia a scrivere i test per le eccezioni. E si sente sempre bene quando vedi i colori verdi quando i tuoi test sono validi;)
  9. E hai finito.

Sicuramente questo approccio richiede anche alcune conoscenze in UML, ma è veloce da imparare. Ed è sempre più veloce rinominare una classe o spostare le frecce in un digramma piuttosto che farlo nel tuo IDE. Ma l'apprendimento dell'uso dei framework di test sarà più estenuante all'inizio. Il meglio è qui per cercare di eseguire test di progetti open source e vedere come funzionano. Ma quando hai una applicazione testata la prossima applicazione sarà molto più veloce. E penso che sia una bella sensazione sapere che tutto funziona bene.

Quindi ho appena votato gli approcci, perché sono molto dispendiosi in termini di tempo per i principianti e, dopotutto, non vanno bene. Per avere un confine pulito tra la struttura e il comportamento, è possibile utilizzare la progettazione guidata dal dominio e in Arrange molto dominio con due pacchetti (un pacchetto denominato struttura e l'altro comportamento denominato). Anche per i tuoi test. esempio semplice controlla questo Esempio scritto in java.

    
risposta data 30.06.2017 - 10:50
fonte
1

The code I'm writing works. It works because I'm testing it manually.

Hai provato manualmente ogni possibile ramo delle tue condizioni dopo un piccolo cambiamento? Quanto tempo richiede il ciclo di feedback dei test manuali. Quanto è vicino al ciclo di feedback che ottieni con i test automatici.

I test automatici (non importa in primo luogo o no) ti fanno andare veloce, fornendo un ciclo di feedback più rapido sul tuo codice.

Sei sicuro di ricordare di testare alcune condizioni manualmente dopo sei mesi - per favore non dire che documenterai tutte le condizioni importanti da testare - perché scrivere tipo di documentazione / commento è uguale a scrivere test (documentazione eseguibile)

  • Pick a vertical slice of work

  • Develop a functioning prototype

  • Refactor until everything is nice and tidy

E ancora: durante il refactoring hai testato manualmente tutta la logica che viene influenzata dal refactoring? Quanto tempo impiega tempo per testare il cambiamento del refactoring? Se il refactoring rompe del codice per quanto tempo impiega a trovare un motivo per le interruzioni?

  • Sit back an appreciate the beautifully SOLID and testable code I've written.

Il codice bello e pulito che hai apprezzato è molto soggettivo. Il tuo codice può essere pulito e ragionevole per te. Il metodo migliore per verificare se il tuo codice è veramente leggibile, comprensibile e controllabile sono i test e le revisioni del codice fatte da altri sviluppatori.

Hai trovato la tua strada molto produttiva solo perché sei solo sviluppatore che lavora con il codice e, penso, perché inizi a lavorare solo in questo progetto (Quanti anni hai lavorato su questo progetto? 6 - 8 mesi?). < br> Ricordi ancora tutto ciò che hai scritto e puoi riconoscere una ragione per possibili problemi. Sono abbastanza sicuro che inizierai a scrivere i test dall'inizio dopo 2-3 anni del tuo progetto, perché vuoi essere sicuro di non dimenticare nulla.

    
risposta data 30.06.2017 - 21:12
fonte
0

Se non commetti errori, non hai davvero bisogno di test. La maggior parte degli sviluppatori commette errori, ma se non lo fai mai e sei sicuro di non commettere errori in futuro (e sei l'unico sul progetto), non c'è davvero alcun motivo per perdere tempo a scrivere test.

Ma la tua soluzione è a metà strada perché stai proponendo di scrivere dei test quando cambi il codice, ma allo stesso tempo il tuo metodo presume che non commetterai mai errori quando decidi quali parti del codice scrivere test per. Funziona solo se capisci perfettamente quali aree possono essere interessate da un cambiamento. Penso che molti sviluppatori comuni (non tu, ovviamente!) Abbiano provato a fare un cambiamento, e poi un test da qualche parte inaspettato fallisce, perché hai fatto un errore.

Ovviamente una buona architettura, i principi SOLID ecc. dovrebbero impedire che ciò accada, ma la maggior parte degli sviluppatori non è perfetta, ed è per questo che i test attraverso il sistema sono preziosi.

    
risposta data 10.06.2015 - 15:31
fonte

Leggi altre domande sui tag