Domanda

Scrivo unit test mentre scrivo API e funzionalità di base. Ma voglio essere il bravo fanboy che mangia, dorme e respira TDD e BDD. Qual è il modo migliore per iniziare con TDD / BDD nel modo giusto? Libri, risorse, quadri, buone pratiche?

Il mio ambiente è backend Java con frontend Grails, integrato con diversi servizi Web e database esterni.

È stato utile?

Soluzione

Un buon punto di partenza è leggere i blog. Quindi acquista i libri delle persone che stanno bloggando. Alcuni lo consiglio vivamente:

" Uncle Bob " Martin e i ragazzi di Object Mentor: http://blog.objectmentor.com/

P.S. ottenere il codice Clean del libro di Bob:

http://www.amazon.com/Clean-Code-Handbook-Software- artigianato / dp / 0132350882

Il mio amico Tim Ottinger (ex Object Mentor dude) http://agileinaflash.blogspot.com/ http://agileotter.blogspot.com/

I ragazzi di Jetbrains: http://www.jbrains.ca/permalink/285

Ho sentito il bisogno di espandermi su questo, poiché tutti gli altri sembrano voler darti la loro opinione su TDD e non aiutarti nella tua missione per diventare un Jedi-Ninja. Michael Jordan di TDD è Kent Beck. Ha davvero scritto il libro su di esso:

http://www.amazon.com/Test-Driven-Development-Kent- Beck / dp / 0321146530

blog anche su:

http://www.threeriversinstitute.org/blog/?p=29

altro " famoso " i sostenitori di TDD includono:

Sono tutte persone fantastiche da seguire. Dovresti anche prendere in considerazione la possibilità di partecipare ad alcune conferenze come Agile 2010 o Software Craftsmanship (quest'anno si sono tenute contemporaneamente a Chicago)

Altri suggerimenti

Non mi piace quando la gente dice " La pratica X non è mai male; se non funziona, non lo stai facendo bene. " Mi dispiace, ha la stessa sensazione di qualsiasi altro dogma religioso troppo zelante. Non lo compro.

Sono d'accordo con quelle persone che sostengono che l'obiettivo migliore dovrebbe essere il tuo tempo e il tuo denaro dovrebbe essere l'obiettivo.

Chiunque si opponga a TDD non dovrebbe essere automaticamente accusato di non tenere conto della qualità. (" Quindi, quando hai smesso di picchiare tua moglie? ") Il fatto è che il software ha dei bug e il costo per eliminarli tutti deve essere valutato rispetto al vantaggio.

Lo stesso vale per la produzione. Le tolleranze su dimensioni e finiture sulle superfici non sono tutte uguali, perché a volte una tolleranza stretta e una finitura a specchio non sono garantite.

Sì, scrivo unit test, anche se non spesso prima di scrivere la classe. Ho visto l'effetto dei test sul design. Misuro e guardo la copertura del codice. Se trovo che la mia copertura non sia accettabile, scrivo altri test. Comprendo il vantaggio di una rete di sicurezza di test unitari per il refactoring. Seguo queste pratiche anche quando lavoro da solo, perché ho sperimentato i benefici in prima persona. Ho capito.

Ma darei uno sguardo interrogativo a qualsiasi compagno di squadra che ha iniziato a infastidirmi su " mangiare, dormire e test dell'unità di respirazione e TDD. "

  

Il mio manager dice che l'unico modo per farmi una promozione è se riesco a portare il team a TDD / BDD.

Hai mai pensato che forse questo ti fa sembrare un succhiatore? Hai scoperto che il tuo fastidio ha alienato il resto della tua squadra?

Questa risposta potrebbe perdere alcuni punti reputazione, ma bisogna dirlo.

Penso che un approccio migliore sarebbe praticarlo da soli e far vedere agli altri il beneficio. Dare l'esempio. Sarà molto più persuasivo che farti andare in bocca.

Accidenti, Grails ha integrato la generazione di test. Se stai lavorando in un team che utilizza Grails, quante altre vendite sono necessarie?

Best practice IMHO: fai ciò che è pratico e non solo perché è un processo. Non dimenticare quale sia l'obiettivo di scrivere applicazioni e, nel mondo degli affari, non è scrivere test. Non fraintendetemi, hanno il loro posto, ma questo non dovrebbe essere l'obiettivo.

Trova qualcuno che sta facendo TDD / BDD e abbina il programma con loro.

Le metriche sono, IMHO, il modo migliore per andare da qui a lì. Tieni traccia di quanto bene è coperto il tuo codice, mantieni i delta della complessità del codice per ogni commit, usa i test-runner che guardano il tuo codice per le modifiche e rieseguono costantemente i test corrispondenti. Non lasciare mai che le lunghezze dei test superino alcune righe, in modo che tutti i tuoi strumenti funzionino bene. E raccomanderei una volta al mese, prendersi un giorno libero per eseguire il codice attraverso un tester di mutazione. Quel giorno dovrebbe essere dedicato solo alla scrittura dei test. Tutte queste cose ti faranno soffrire se non stai già facendo un buon TDD. Impara dal dolore e in pochissimo tempo lo farai nel modo giusto.

E non perdere mai di vista a cosa servono i test: per descrivere il comportamento desiderato. Sono le tue specifiche eseguibili. (Questo è anche il motivo per cui mi piace Cucumber ; ora puoi ottenere il tuo PHB per scrivere i tuoi test per te! Beh, forse no abbastanza bene, ma è vicino!)

" PS: Il mio manager dice che l'unico modo per farmi una promozione è se riesco a portare il team a TDD / BDD. "

L'unico modo realistico per convincere una squadra a fare qualcosa (senza ucciderti nel processo) è quello di dimostrare loro chiaramente che sarà vantaggioso per loro cambiare le proprie abitudini. In altre parole, scrivi il codice. Un sacco di codice. Tonnellate di codice. E poi quando arriva l'e-mail cruciale che altera radicalmente le specifiche, mostra loro che puoi modificare facilmente il tuo codice con refactoring e, peggio ancora, perché eri preparato con i test sul posto. Il bar era verde, hack hack, RED BAR !!!!, hack hack, barra verde, vai a casa.

Leggi il libro di Kent Becks sulla progettazione guidata dai test. Inizia con i test e poi esegui il codice. Ottieni un server di build in esecuzione che ESEGUE LE PROVE! Non hai bisogno di averlo per tutto il team, fallo per te stesso e MOSTRALO che aiuta.

La predicazione infastidisce solo i nativi :)

Faccio TDD da un paio d'anni, ma ultimamente ho iniziato a studiare meglio il modo in cui BDD guida il mio design e sviluppo. Le risorse che mi hanno aiutato a iniziare su BDD sono state il primo e il più recente blog di Dan North (il "fondatore" di BDD). Dai un'occhiata a Presentazione di BDD . C'è anche un Wiki BDD "ufficiale" su behaviour-driven.org con alcuni buoni post che vale la pena leggere.

L'unica cosa che ho trovato molto difficile quando ho iniziato con BDD (e trovo ancora un po 'difficile) è come formulare quegli scenari per renderli adatti al BDD. Scott Bellware è un uomo esperto in BDD (o Context-Spesification come gli piace coniare) e il suo articolo Sviluppo guidato dal comportamento in Code Magazine mi ha aiutato molto a capire il modo di pensare e formulare storie degli utenti BDD.

Consiglierei anche TekPub screencast Design orientato al comportamento con specflow di Rob Conery. Un'ottima introduzione a BDD e ad uno strumento (SpecFlow) molto adatto per fare BDD in C #.

Per quanto riguarda le risorse TDD, ci sono già molti buoni consigli qui. Ma voglio solo sottolineare un paio di libri che posso davvero consigliare;

Per iniziare, esegui i test unitari, poi leggi come fare per ultimo insegnando al tuo team come fare TDD e metterli a bordo - perché nella mia esperienza niente è più importante del test unitario con tutto il tuo team.

Avrai anche bisogno di un corretto processo di compilazione - utilizzando un server di compilazione che costruisca il tuo codice ed esegua il tuo test, ti consiglio di usare TeamCity (gratuito con limitazioni).

Imparare a correggere buoni test unitari è la parte difficile: in parte imparerai da solo (finché continuerai i test unitari) e il resto potrai imparare dalla ricerca in Internet.

Saprai di aver raggiunto il tuo obiettivo quando NON scrivere unità di test come parte dello sviluppo ti sembrerà sbagliato.

Ricorda, agile significa che non sei completamente esaurito con un metodo particolare. Se stai lavorando a qualcosa in cui i vantaggi di TDD non valgono la pena (come apportare modifiche di prova ed errore su un'interfaccia Swing), allora non utilizzare TDD.

Non riesco a vedere che qualcuno abbia davvero espresso che TDD non è non sui test. TDD-ing consiste nell'esprimere il comportamento previsto prima di apportare la piccola modifica che cambia il comportamento. Ciò migliora notevolmente il design e consente la messa a fuoco in un modo che non avevo mai sperimentato prima. Ottieni test che proteggono i tuoi futuri refactoring e una copertura del 90% gratuita.

Per impararlo suggerirei (riassumendo ciò che altri hanno detto e aggiungendo uno dei miei):

  1. visita i blog e leggi i libri sopra menzionati
  2. fai coppia con qualcuno che sia esperto di TDD
  3. pratica

Ho praticato il kata di Bowling (esercizio) da solo circa 20 volte (circa 30 minuti ciascuno) prima di iniziare a vedere la luce. Iniziato analizzando la descrizione di Zio Bob qui . Ci sono molti kata sul sito codingdojo.org tra cui soluzioni e discussioni. Provali!

Per prendere un preventivo da Nike: basta farlo.

Secondo consiglio: non fare mai affidamento sull'interfaccia di qualcun altro. Scrivi sempre, a livello di ogni classe, sull'interfaccia che desideri esistesse - scrivi un adattatore per l'implementazione effettiva, se necessario.

Inoltre, trovo utile evitare valori di ritorno sui metodi e pensare al codice in termini di passaggio dei messaggi piuttosto che di chiamate di funzione.

YMMV.

Un anno fa, avevo poca idea su come fare il TDD (ma volevo davvero (quanto frustrante)) e non avevo mai sentito parlare di BDD ... ora faccio entrambi in modo compulsivo. Sono stato in un ambiente di sviluppo .Net, non Java, ma ho persino sostituito il & Quot; F5 - Esegui & Quot; pulsante con una macro per eseguire Cucumber (BDD) o MBUnit (TDD) a seconda che si tratti di una caratteristica / scenario o specifica. Nessun debugger se possibile. $ 1 nel barattolo se si utilizza il debugger (JOKING (sorta di)).

Il processo è davvero fantastico. Il framework che stiamo inoltre utilizzando è di Oracle, di cui ho avuto la fortuna di imbattermi e di assorbire informazioni, e quel framework che usiamo è MavenThought.

Tutto inizia con BDD. Il nostro BDD è un cetriolo in cima al rubino di ferro.

Caratteristica:

Scenario: ....    Dato che faccio blah ...
   Quando faccio qualcos'altro ...    Quindi accadono cose meravigliose ...

Scenario: ...

E questo non è lo stesso test unitario, ma guida la funzionalità, scenario per scenario e, a sua volta, le specifiche dell'unità (test). Quindi inizi da uno scenario e con ogni passaggio devi completare nello scenario guida il tuo TDD.

E il TDD che stiamo usando è un po 'un BDD in un certo senso, perché osserviamo i comportamenti richiesti dal SUT (System Under Test) e viene specificato un comportamento per specifica (classe " test " file).

Esempio:

Ecco le specifiche per un comportamento: quando viene creato il sistema in prova.

Esiste un'altra specifica (file di classe C # When_blah_happens) per un altro comportamento quando una proprietà cambia, ma che viene separata in un file separato.

using MavenThought.Commons.Testing;
using SharpTestsEx;

namespace Price.Displacement.Module.Designer.Tests.Model.Observers
{
    /// <summary>
    /// Specification when diffuser observer is created
    /// </summary>
    [ConstructorSpecification]
    public class When_diffuser_observer_is_created
        : DiffuserObserverSpecification
    {
        /// <summary>
        /// Checks the diffuser injection
        /// </summary>
        [It]
        public void Should_return_the_injected_diffuser()
        {
            Sut.Diffuser.Should().Be.SameInstanceAs(this.ConcreteDiffuser);
        }
    }
}

Questo è probabilmente il comportamento più semplice per un SUT, perché in questo caso quando viene creato, la proprietà Diffuser dovrebbe essere la stessa del diffusore iniettato. Ho dovuto usare un Diffusore in cemento invece di un Mock perché in questo caso il Diffusore è un oggetto Core / Dominio e non ha una notifica di proprietà per l'interfaccia. Il 95% delle volte ci riferiamo a tutte le nostre dipendenze come Dep (), invece di iniettare la cosa reale.

Spesso abbiamo più di una [It] Should_do_xyz (), e talvolta un bel po 'di setup come forse fino a 10 linee di stub. Questo è solo un esempio molto semplice senza GivenThat () o AndGivenThatAfterCreated () in quella specifica.

Per la configurazione di ogni specifica in genere è sempre necessario sostituire solo un paio di metodi della specifica:

GivenThat () == > ciò accade prima della creazione di SUT.

CreatSut () == > Deridiamo automaticamente la creazione del sut con StructureMap e il 90% del tempo non ha mai bisogno di sovrascrivere questo, ma se sei un costruttore che sta iniettando un Concrete, devi ignorarlo.

AndGivenThatAfterCreated () = > questo succede dopo la creazione di SUT.

WhenIRun () = > a meno che non sia un [ConstructorSpecification] lo usiamo per eseguire UNA riga di codice che è il comportamento che stiamo specificando per il SUT

Inoltre, se esiste un comportamento comune di due o più specifiche dello stesso SUT, lo spostiamo nella specifica di base.

Tutto quello che devo fare per eseguire la specifica è evidenziare il suo nome, esempio " When_diffuser_observer_is_created " e premi F5, perché ricorda, per me F5 esegue un'attività Rake test: feature [tag] se Cucumber o test: class [SUT]. Ha senso per me perché ogni volta che esegui il debugger è un lancio, non viene creato alcun codice (oh e costa $ 1 (scherzando)).

Questo è un modo molto, molto pulito per specificare il comportamento con TDD e avere SUT davvero semplici e specifiche semplici. Se provi ad essere un programmatore di cowboy e scrivi il SUT schifoso con forti dipendenze, ecc., Sentirai il dolore di provare a fare TDD e stufarti / arrenderti O mordere il proiettile e farlo bene.

Ed ecco l'attuale SUT. Abbiamo un po 'di fantasia e usiamo PostSharp per aggiungere la notifica della proprietà modificata sul Diffusore, quindi Post.Cast < > ;. E ancora, ecco perché ho iniettato un Concrete piuttosto che un Mock. Ad ogni modo, come puoi vedere il comportamento mancante definito in un'altra specifica è quando qualcosa cambia sul Diffusore.

using System.ComponentModel;
using MavenThought.Commons.Events;
using PostSharp;
using Price.Displacement.Core.Products;
using Price.Displacement.Domain;

namespace Price.Displacement.Desktop.Module.Designer.Model.Observers
{
    /// <summary>
    /// Implementation of current observer for the selected product
    /// </summary>
    public class DiffuserObserver : AbstractNotifyPropertyChanged, IDiffuserObserver
    {
        /// <summary>
        /// gets the diffuser
        /// </summary>
        public IDiffuser Diffuser { get; private set; }

        /// <summary>
        /// Initialize with a diffuser
        /// </summary>
        /// <param name="diffuser">The diffuser to observe</param>
        public void Initialize(IDiffuser diffuser)
        {
            this.Diffuser = diffuser;
            this.NotifyInterface().PropertyChanged += (x, e) => this.OnPropertyChanged(e.PropertyName);
        }

        /// <summary>
        /// Gets the notify interface to use
        /// </summary>
        /// <returns>The instance of notify property changed interface</returns>
        protected INotifyPropertyChanged NotifyInterface()
        {
            return Post.Cast<Diffuser, INotifyPropertyChanged>((Diffuser)Diffuser);
        }
    }
}

In conclusione, questo stile di sviluppo BDD / TDD oscilla. Ci è voluto un anno, ma sono un totale convertito come stile di vita. Non avrei imparato questo da solo. Ho raccolto tutto da The Oracle http://orthocoders.com/ .

Pillola rossa o blu, a te la scelta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top