Qual è la differenza tra scrivere casi di test per BDD e TDD? [duplicare]

243

Ho imparato a scrivere casi di test per BDD (Behavior Driven Development) usando specflow. Se scrivo test completi con BDD, è necessario scrivere separatamente il test TDD (Test Driven Development)? È necessario scrivere separatamente i casi di test sia per TDD che per BDD oppure sono effettivamente la stessa cosa?

Mi sembra che entrambi siano uguali, con l'unica differenza che i casi di test BDD possono essere capiti da non sviluppatori e tester.

    
posta arjun 15.02.2012 - 17:59
fonte

8 risposte

212

La differenza tra BDD e TDD è che BDD inizia con un B e TDD inizia con un T. Ma seriamente, il guaio con TDD è che troppi sviluppatori si sono concentrati sul "Come" quando scrivevano i loro test unitari, così finirono con test molto fragili che non hanno fatto altro che confermare che il sistema fa quello che fa.

BDD fornisce un nuovo vocabolario e quindi si concentra sulla scrittura di un test unitario. Fondamentalmente è un approccio guidato dalla TDD.

    
risposta data 15.02.2012 - 20:06
fonte
50

Lo sviluppo guidato dal comportamento è un'estensione / revisione dello sviluppo basato su test. Il suo scopo è di aiutare le persone che escogitano il sistema (cioè gli sviluppatori) a identificare test appropriati da scrivere, cioè test che riflettano il comportamento desiderato dagli stakeholder. L'effetto finisce per essere lo stesso: sviluppare il test e quindi sviluppare il codice / sistema che supera il test. La speranza in BDD è che i test siano effettivamente utili per dimostrare che il sistema soddisfa i requisiti.

Aggiorna

Le unità di codice (metodi individuali) potrebbero essere troppo granulari per rappresentare il comportamento rappresentato dai test comportamentali, ma dovresti comunque testarle con test unitari per garantire che funzionino in modo appropriato. Se questo è ciò che intendi per test "TDD", allora sì, ne hai ancora bisogno.

    
risposta data 15.02.2012 - 18:09
fonte
25

BDD utilizza qualcosa chiamato "Ubiquitous Language", un insieme di conoscenze che può essere compreso sia dallo sviluppatore che dal cliente. Questo linguaggio ubiquitario viene utilizzato per modellare e sviluppare i requisiti e i test necessari, a livello di comprensione del cliente.

Entro i confini dei requisiti e dei test dettati da BDD, utilizzerai il TDD "ordinario" per sviluppare il software. I test unitari così creati serviranno come una suite di test per il codice di implementazione, mentre i test BDD funzioneranno più o meno come test di accettazione per il cliente.

    
risposta data 15.02.2012 - 18:07
fonte
20

Nella mia esperienza il problema più grande con TDD è " T ". Fa sì che il laico (manager, tester, sviluppatori non TDD) lo identifichino nelle loro menti con la tradizionale fase di "Testing" post-sviluppo di uno stile a cascata. Questo è qualcosa che chiunque può capitare.

Il problema con cui molti combattono è che TDD è per gli sviluppatori, non per i tester. Fatto bene, il TDD non è principalmente una strategia di test o uno strumento di test di accettazione, ma una tecnica che guida il buon design del software da zero: classi piccole e vagamente accoppiate, interfacce chiare e ben definite e codice continuamente pulito attraverso il refactoring continuo. Refactoring che viene eseguito regolarmente, frequentemente e da una posizione di confidenza.

Che ti capita di trovare una suite di test completa che può formare parte del tuo processo di creazione / configurazione è un bonus, non l'obiettivo.

BDD lo complica colmando il divario tra i requisiti aziendali e i test di accettazione di livello superiore. È la soddisfazione della suite BDD che esamina il processo di sviluppo e che determina quando il prodotto nel suo insieme è stato adeguatamente consegnato.

    
risposta data 06.04.2014 - 23:46
fonte
19

Le differenze tra TDD e BDD sono sottili e in gran parte si riducono a lingua . I test BDD vengono spesso scritti nel seguente formato:

public void shouldBuyBread() throws Exception {
   //given  
   given(seller.askForBread()).willReturn(new Bread());

   //when
   Goods goods = shop.buyBread();

   //then
   assertThat(goods, containBread());
 }  

Se inquadra il test in termini di comportamento , aiuta a comprendere la responsabilità della classe e porta a un design migliore (almeno secondo i BDD'er). BDD a volte si concentra su specifiche eseguibili che i tuoi esperti di dominio / clienti possono comprendere.

BDD è anche più associato a ciò che Martin Fowler chiama test "fuori dall'interno" o "mockist" , al contrario alla verifica basata sullo stato.

    
risposta data 15.02.2012 - 19:49
fonte
12

Dato che la mia ultima risposta non ha avuto molto successo, tenterò un approccio molto semplice.

  • Behaviour Driven Development è un sottoinsieme di Test Driven Development
  • TDD si concentra su ogni unità di test per ogni funzione, non importa ciò che fa. BDD si concentra su software che conta
  • Idiom . TDD setta per i test, BDD applica racconto formato

Esempi di JavaScript

Test unitari in jasmine ( BDD )

describe("A suite", function() {
  it("contains spec with an expectation", function() {
    expect(true).toBe(true);
  });
});

Test unitari in jsUnity ( TDD )

function test_lists() { assert.areEqual([1, 2, 3], [1, 2, 3]) }

Ecco alcune librerie Python che aiutano a creare più BDD come test con framework unittest:

  • Lattuga : Cetriolo per python
  • HamCrest
risposta data 14.01.2014 - 05:33
fonte
4

BDD aggiunge un ulteriore livello di astrazione ai test. Il codice di livello superiore (di solito in txt) descrive cosa prova il sistema, il codice di livello inferiore descrive come lo testa. Quindi un framework BDD può utilizzare un framework TDD nel codice di livello inferiore.

Questo aiuta molto rimanendo ASCIUTTO. Con TDD puoi facilmente finire con i test "umidi" che contengono molte duplicazioni di codice, che li rendono facili da rompere rifattorizzando il codice e i test con esso. Con BDD devi modificare solo il livello di astrazione inferiore effettuando il refactoring del codice, quindi se la specifica non cambia, il codice di livello superiore non cambierà.

Btw. questo è semplice codice pulito, in genere è sufficiente leggere l'alto livello di astrazione per capire cosa fa e scavare più a fondo nel codice di test del livello di astrazione inferiore solo se ne hai davvero bisogno. Questo rende il codice (test) più facile da capire in generale.

Un cattivo esempio (perché è troppo semplice):

stile TDD jasmine

calculator.add.specs

describe("Calculator: add", function (){

    it("should be able to add 2 numbers together", function (){
        var total = add(1, 2);
        expect(total).toBe(3);
    });

    it("should be able to add 3 numbers together", function (){
        var total = add(1, 2, 3);
        expect(total).toBe(6);
    });
});

stile BDD jasmine-cetriolo

calculator.specs

feature('Calculator: add')
    .scenario('should be able to add 2 numbers together')
        .when('I enter "1"')
        .and('I add "2"')
        .then('I should get "3"')
    .scenario('should be able to add 3 numbers together')
        .when('I enter "1"')
        .and('I add "2"')
        .and('I add "3"')
        .then('I should get "6"')

calculator.steps

featureSteps('Calculator:')
    .before(function(){
        this.values = [];
        this.total = null;
    })
    .when('I enter "(.*)"', function(value){
        this.values.push(Number(value));
    })
    .when('I add "(.*)"', function(value){
        this.values.push(Number(value));
    })
    .then('I should get "(.*)"', function(expectedTotal){
        this.total = add.apply(null, this.values);
        expect(this.total).toBe(Number(expectedTotal));
    });

applicazione

calculator.js

function add(){
    var args = Array.prototype.slice.call(arguments);
    var total = 0;
    for (var i in args)
        total += args[i];
    return total;
}

Ora se cambio la funzione add() in sum() devo cambiare il codice TDD in 2 posizioni, mentre il codice BDD solo in un posto singolo nel file passi . Ofc. aggiungere un altro livello di astrazione richiede più codice ...

    
risposta data 21.05.2015 - 23:07
fonte
2

Solo per mantenere la confusione, renditi conto che molte persone ora associano BDD al cetriolo. Considera che qualsiasi test che scrivi usando la sintassi derivata da gherkin sia un controllo BDD, e qualsiasi cosa scritta usando un quadro di test unitario (junit, unittest.py, ecc.) Sia TDD.

È sbagliato. Il mezzo non definisce il messaggio in questo caso. Né l'uso di mock (IMHO).

La principale differenza era già data: il BDD è una tecnica orientata alle funzionalità, che usa un linguaggio ubiquo e un approccio esterno. Scriviamo specifiche (che verranno poi eseguite come test) per una storia o una fetta di una storia. La piccolezza e la concretezza contano, ed è una "spiegazione per esempio" di ciò che è necessario / previsto da questo aspetto della storia.

Le specifiche BDD vengono spesso scritte in un linguaggio simile a un cetriolino se le persone che devono specificare la funzione non leggono / scrivono codice (caso frequente in organizzazioni più grandi o dove un vero cliente fa parte del team). Altrimenti, il cetriolino non è necessario. Questi tendono ad essere l'output del famoso 3 meeting di Amigos: business, test, dev fanno tutti insieme. Quando si utilizza un framework BDD (fit, cetriolo, ecc.) Il test è più lento e richiede un po 'più di infrastruttura, quindi manteniamo questi relativamente scarsi, alcuni per piano.

TDD viene utilizzato durante la creazione del codice. Lo scopo è quello di dare una progressione ordinata di scrivere la funzione con molte opportunità per il refactoring e con una ragionevole sicurezza che non stai rompendo nulla accidentalmente mentre scrivi il nuovo codice. Non ha bisogno di descrivere le caratteristiche del sistema, solo di un metodo (o alcuni con un effetto comune). Nessuno, a parte gli sviluppatori, ha bisogno di leggere i test scritti qui, ma devono correre velocemente e isolare gli errori. Funzionano velocemente perché potrebbero esserci molti test per ogni funzione membro della classe ('metodo').

Se si esegue il BDD sul livello esterno, è comunque utile eseguire TDD nel ciclo interno a causa del refactoring e della capacità di individuare ed evitare errori più rapidamente.

Né è la prova di correttezza per un grande sistema. Né sostituisce i test di penna e perf. Né garantisce la sicurezza del filo. I test sono aiuti per lo sviluppo, non garanzie di perfetta sicurezza contro i bug.

    
risposta data 22.05.2015 - 19:07
fonte

Leggi altre domande sui tag