Il tuo capo non apprezzerà il TDD: prova questo esempio di sviluppo basato sul comportamento
Pubblicato: 2022-03-11Test. Spesso viene lasciato all'ultimo minuto, quindi tagliato perché sei fuori tempo, fuori budget o qualsiasi altra cosa.
Il management si chiede perché gli sviluppatori non possano semplicemente "fare le cose bene la prima volta" e gli sviluppatori (soprattutto su sistemi di grandi dimensioni) possono essere presi alla sprovvista quando diversi stakeholder descrivono parti diverse del sistema, come la storia dei ciechi che descrivono un elefante.
È inevitabile, tuttavia, che il primo passo di ogni progetto sia una discussione sui comportamenti del software o delle funzionalità da realizzare. Un cliente o un uomo d'affari si avvicina a qualcuno del team di sviluppo e spiega cosa vuole.
A volte queste interazioni si presentano sotto forma di una user story Agile. A volte si presentano sotto forma di documenti di progettazione, come nel post sul blog di Chris Fox l'anno scorso. Potrebbero anche venire come diagrammi di flusso o modelli in Keynote o persino telefonate affrettate.
Da queste sole comunicazioni, uno sviluppatore è responsabile della costruzione di un sistema che "funziona e basta". Ciò è particolarmente difficile per i liberi professionisti che lavorano al di fuori del sistema più ampio.
Perché i test vengono tagliati?
C'è una lacuna evidente qui: se l'imprenditore ha previsto i comportamenti del sistema all'inizio, perché testare che questi comportamenti funzionino effettivamente spesso il passaggio che viene tagliato?
La risposta può essere incredibilmente semplice: i test spesso non sono visti come capitale condiviso ; non si pensa che abbiano valore per il progetto, perché “sono solo per gli ingegneri” o, allo stesso modo, forniscono valore a un singolo dipartimento o gruppo di persone.
Come testiamo questo capitale condiviso, questo elenco di comportamenti del sistema? Abbracciando non solo lo sviluppo guidato dai test (TDD), ma anche lo sviluppo guidato dal comportamento (BDD).
Cos'è BDD?
Lo sviluppo basato sul comportamento dovrebbe essere incentrato sui comportamenti aziendali che il tuo codice sta implementando: il "perché" dietro il codice . Supporta un flusso di lavoro incentrato sul team (soprattutto interfunzionale).
Ho visto agile BDD funzionare davvero bene quando uno sviluppatore e il proprietario del prodotto Agile o un analista aziendale si siedono insieme e scrivono le specifiche in sospeso (che saranno compilate in seguito dallo sviluppatore) in un semplice editor di testo:
- L' uomo d'affari specifica i comportamenti che desidera vedere nel sistema.
- Lo sviluppatore pone domande in base alla sua comprensione del sistema, scrivendo anche comportamenti aggiuntivi necessari dal punto di vista dello sviluppo.
Idealmente, entrambe le parti possono fare riferimento all'elenco dei comportamenti di sistema correnti per vedere se questa nuova funzionalità interromperà le funzionalità esistenti.
Ho scoperto che questo semplice atto mi dà abbastanza vincoli che sono in grado di pensare come uno sviluppatore: "dato che devo implementare questi test, come fa a vincolare me/tutti alle specifiche che posso implementare nel codice"? Dal momento che sono in attesa di specifiche, sono veloci e facili da scrivere nel bel mezzo della collaborazione.
Questo approccio collaborativo mi consente di concentrarmi su ciò che la funzionalità offre all'utente finale e avere l'uomo d'affari proprio lì mi costringe a parlare di comportamento, non di implementazione. Ciò evidenzia le differenze tra BDD e TDD.
Vediamo un esempio di sviluppo guidato dal comportamento
Lo scenario: sei uno sviluppatore in un team responsabile del sistema di contabilità aziendale, implementato in Rails. Un giorno, un uomo d'affari ti chiede di implementare un sistema di promemoria per ricordare ai clienti le fatture in sospeso. Perché stai praticando BDD per questo tutorial; (rispetto a TDD), ti siedi con quell'uomo d'affari e inizi a definire i comportamenti.
Apri il tuo editor di testo e inizi a creare specifiche in sospeso per i comportamenti desiderati dall'utente aziendale:
it "adds a reminder date when an invoice is created" it "sends an email to the invoice's account's primary contact after the reminder date has passed" it "marks that the user has read the email in the invoice"
Questa attenzione al comportamento durante lo sviluppo rende il test utile come verifica che stai creando la funzionalità giusta, non solo che il tuo codice sia corretto. Si noti che la formulazione è nel linguaggio commerciale, non nel linguaggio di implementazione interna del sistema. Non vedi o ti interessa che una fattura belongs_to
un account, perché nessuno al di fuori del team di sviluppo si preoccupa di questo.
Alcuni sviluppatori preferiscono scrivere casi di test sul posto, chiamando metodi nel sistema, impostando aspettative, in questo modo:
it "adds a reminder date when an invoice is created" do current_invoice = create :invoice current_invoice.reminder_date.should == 20.days.from_now end
La suite di test fallirà perché dobbiamo ancora scrivere il codice per impostare il reminder_date
.
Di fronte a specifiche difettose
Capisco gli sviluppatori che scrivono specifiche non corrette, ma con l'uomo d'affari al mio fianco, questo non ha mai funzionato per me. L'uomo d'affari sbagliato verrà distratto dai dettagli o prenderà questa nuova conoscenza e proverà a microgestire le cose di cui lo sviluppatore sa di più (progettazione corretta del database, riutilizzo del codice).
Nella mia esperienza, scrivere più di una panoramica di una riga di un comportamento specifico annoierà l'uomo d'affari. Lo vedranno come un cattivo uso del loro tempo o diventeranno ansiosi di descrivere il prossimo comportamento mentre è nella loro mente.
In cosa differisce BDD da TDD?
Diamo un'occhiata a questo in un modo diverso, con un approccio di sviluppo basato su test, e scriviamo i test in sospeso:
it "after_create an Invoice sets a reminder date to be creation + 20 business days" it "Account#primary_payment_contact returns the current payment contact or the client project manager" it "InvoiceChecker#mailer finds invoices that are overdue and sends the email"
Questi test sono utili, ma utili solo a un gruppo di persone: gli ingegneri. BDD è utile per comunicare con ogni membro di un team di prodotto interfunzionale.
Puoi certamente eseguire lo sviluppo test-first mentre sei in una mentalità BDD attraverso l'uso di comportamenti in sospeso. Per prima cosa, scrivi il test; quindi eseguilo (rosso); quindi fallo funzionare (verde); quindi correggilo (refactor).

Molto lavoro nella comunità BDD è stato fatto per rendere i controlli delle asserzioni all'interno del test letti come l'inglese. Ecco un test RSpec stereotipato:
a = 42 a.should == 42
Questo formato rende le cose più facili da leggere in seguito. Ma ricorda che questo non è ciò che stiamo facendo qui - il punto è ridurre i comportamenti il più velocemente possibile - e applicare il principio di "un comportamento testato per specifica". Idealmente, il titolo delle specifiche in sospeso dovrebbe dirti cosa stai testando.
BDD non riguarda modi fantasiosi per convalidare i risultati; si tratta di condividere i comportamenti attesi tra tutti i membri del team.
Lo sviluppo basato sul comportamento riguarda la collaborazione e la comunicazione
Facciamo un passo indietro nel nostro scenario: lavorare sul sistema contabile aziendale.
Passi attraverso la funzionalità dell'elemento con l'uomo d'affari, con te che analizzi il sistema attraverso i suoi interni (come gli oggetti si adattano insieme internamente) e loro che analizzano il sistema dall'esterno.
Pensi ad alcune condizioni e chiedi all'analista aziendale cosa succede nei seguenti scenari:
* What's the default reminder date going to be? How many days before the invoice due date? * Are those business days or just calendar days? * What happens if there's not a primary contact associated with the account?
E ottieni risposte . È importante che l'uomo d'affari capisca che non stai cercando di fare buchi nella sua idea di animale domestico o di essere eccessivamente pedante.
In questo modo, lo sviluppo basato sul comportamento è uno strumento per favorire la collaborazione e avviare una conversazione tra i due dipartimenti. È anche un modo per chiarire l'ambito di una funzionalità desiderata e ottenere stime migliori dal team di sviluppo. Forse ti rendi conto che non c'è modo di calcolare 10 giorni lavorativi da un determinato momento; questa è una funzionalità aggiuntiva, separata, che dovrai implementare.
Gli sviluppatori avranno considerazioni da parte degli sviluppatori ("Cosa intendi esattamente quando dici 'giorno'?"), mentre gli uomini d'affari avranno le proprie considerazioni ("Per favore, non usare il termine in ritardo qui, significa qualcosa di diverso"). Il fatto che un gruppo o l'altro se ne vadano e provino a scrivere questi test di comportamento di logica aziendale (la promessa di Cucumber) elimina il prezioso input di ciascuna parte.
È anche un buon sostituto per quando il Cliente Agile non è più fisicamente nella stanza: avere i propri desideri su carta, mescolati con l'analisi (e la traduzione) degli sviluppatori di ciò che stai costruendo.
Documenti di progettazione
Un precedente post sul blog di Toptal Chris Fox parla di documenti di progettazione, specialmente all'inizio di un progetto. Comprendere ed estrarre i comportamenti aziendali si riduce da progetti in cui il sistema è in qualche modo conoscibile, a quelli che richiedono decenni di programmatore-anni per realizzare e avere centinaia o migliaia di specifiche comportamentali.
L'articolo di Chris menziona anche i comportamenti degli elementi sullo schermo, e questa è un'area in cui sono costantemente in disaccordo con i designer: "Che aspetto ha questo pulsante quando è scuro" o "Come appare su 11 schermi", perché questa pagina è ovviamente progettata per schermi da 24 pollici?" Questo avanti e indietro con l'uomo d'affari può trovare lacune nelle risorse grafiche di un progetto o nel layout di una pagina.
In team interfunzionali molto grandi, ci sono molti membri del team con le proprie preoccupazioni: designer, sviluppatori, potenzialmente qualcuno delle operazioni, l'amministratore del database, forse persone del QA (sì, c'è posto per tutti in TDD e BDD!), ognuno con le proprie preoccupazioni e domande. BDD può guidare questa collaborazione più di quanto non faccia lo sviluppo basato su test. Da "cosa succede quando i dati sono troppo grandi per questa tabella?" a, "Hmmm, sarà una query costosa, vorremo memorizzarla nella cache in qualche modo" a "Aspetta, l'utente dovrebbe vedere tutte quelle informazioni riservate?", la posta in gioco potrebbe essere più di un semplice sviluppatore e un analista aziendale con domande su questa nuova funzionalità
Lo sviluppo basato sul comportamento riguarda gli artefatti condivisi
Che cos'è un artefatto condiviso?
Mi piace pensare agli "artefatti" nell'ingegneria del software come cose potenzialmente fisiche che descrivono il progetto o il team di progetto e che sono reperibili dopo sei mesi. I buoni artefatti spiegano perché le cose sono come sono.
Le conversazioni in corridoio non sono artefatti. Né lo sono i disegni su lavagna. Disegni su lavagna che vengono trasformati in grandi documentazioni di classe o documenti di progettazione: questi sono artefatti. Anche i verbali delle riunioni sono artefatti.
Un artefatto è un codice sorgente salvato in un repository o in uno spazio condiviso, e ticket nel sistema di ticket, o note sul Wiki interno o persino registri di chat persistenti.
Gli artefatti condivisi sono, nella mia mente, i migliori artefatti . Mostrano non solo perché qualcosa è così com'è, ma perché esiste nell'app.
Come li usi in BDD?
I comportamenti dovrebbero essere un artefatto del team condiviso: i test non dovrebbero essere solo un lavoro impegnativo per i programmatori! Mentre è meglio avere un sistema in cui l'intero team può facilmente visualizzare le specifiche correnti (forse il sistema di distribuzione estrae e salva anche l'elenco dei comportamenti in un'area privata del sito o in un wiki), potresti anche farlo manualmente ogni sprint.
Il nome del gioco è "aiutare gli sviluppatori a creare le specifiche di cui abbiamo bisogno per fornire valore aziendale più rapidamente, collaborare tra i reparti e fare stime migliori".
Anche questa comprensione a livello aziendale di ciò che fa il sistema è una forma di capitale. È il "perché" del "come" del codice.
Conclusione
Come risolviamo il problema della consegna di software difettoso ai clienti? Facendo in modo che i test non siano visti come qualcosa a cui interessano solo gli sviluppatori.
Descrivere e comprendere le esigenze di un sistema ha un sacco di vantaggi oltre alla correttezza del codice: stabilire un dialogo interdipartimentale e assicurarsi che tutte le preoccupazioni delle parti interessate siano soddisfatte (e non solo le parti interessate con grandi titoli di fantasia). Utilizzare lo sviluppo basato sul comportamento per comprendere queste esigenze fin dall'inizio e testare i comportamenti aziendali esterni a cui l'intero team si preoccupa : è un ottimo modo per garantire un progetto di qualità.