Qual é a diferença entre escrever casos de teste para BDD e TDD? [duplicado]

243

Eu tenho aprendido a escrever casos de teste para BDD (Behavior Driven Development) usando specflow. Se eu escrever testes abrangentes com o BDD, é necessário escrever separadamente o teste TDD (Test Driven Development)? É necessário escrever casos de teste para TDD e BDD separadamente, ou eles são efetivamente a mesma coisa?

Parece-me que ambos são iguais, a única diferença é que os casos de teste do BDD podem ser entendidos por não desenvolvedores e testadores.

    
por arjun 15.02.2012 / 17:59
fonte

8 respostas

212

A diferença entre o BDD e o TDD é que o BDD começa com um B e o TDD começa com um T. Mas, sério, a pegadinha com o TDD é que muitos desenvolvedores focaram no "How" ao escrever seus testes unitários, então eles terminaram com testes muito frágeis que não fizeram nada mais do que confirmar que o sistema faz o que faz.

O BDD fornece um novo vocabulário e, portanto, concentra-se em escrever um teste de unidade. Basicamente, é uma abordagem baseada em recursos para o TDD.

    
por 15.02.2012 / 20:06
fonte
50

O Desenvolvimento Orientado por Comportamento é uma extensão / revisão do Desenvolvimento Orientado a Testes. Sua finalidade é ajudar as pessoas que planejam o sistema (ou seja, os desenvolvedores) a identificar os testes apropriados para escrever - isto é, testes que refletem o comportamento desejado pelas partes interessadas. O efeito acaba sendo o mesmo - desenvolva o teste e depois desenvolva o código / sistema que passa no teste. A esperança no BDD é que os testes sejam realmente úteis para mostrar que o sistema atende aos requisitos.

UPDATE

Unidades de código (métodos individuais) podem ser muito granulares para representar o comportamento representado pelos testes comportamentais, mas você ainda deve testá-los com testes de unidade para garantir que eles funcionem apropriadamente. Se é isso que você quer dizer com testes "TDD", então sim, você ainda precisa deles.

    
por 15.02.2012 / 18:09
fonte
25

O BDD utiliza algo chamado "Linguagem Ubíqua", um corpo de conhecimento que pode ser entendido pelo desenvolvedor e pelo cliente. Essa linguagem onipresente é usada para moldar e desenvolver os requisitos e testes necessários, no nível do entendimento do cliente.

Dentro dos limites dos requisitos e testes ditados pelo BDD, você usará o TDD "comum" para desenvolver o software. Os testes de unidade assim criados servirão como um conjunto de testes para o código de implementação, enquanto os testes do BDD funcionarão mais ou menos como testes de aceitação para o cliente.

    
por 15.02.2012 / 18:07
fonte
20

Na minha experiência, o maior problema com o TDD é o " T ". Isso faz com que o leigo (gerentes, testadores, desenvolvedores não-TDD) o equacionem em suas mentes com a fase tradicional de "teste" de pós-desenvolvimento de um estilo cascata. Isso é algo que qualquer um pode entender.

O problema com o qual muitos lutam é que o TDD é para desenvolvedores, não para testadores. Feito corretamente, TDD não é primariamente uma estratégia de teste ou uma ferramenta de teste de aceitação, mas uma técnica que impulsiona desde o zero o bom design de software - classes pequenas e fracamente acopladas, interfaces claras e bem definidas e código continuamente limpo por meio de refatoração contínua. Refatoração que é executada rotineiramente, com frequência e de uma posição de confiança.

O fato de você ter uma suíte de testes abrangente que pode formar parte do seu processo de CI / build é um bônus, não o objetivo.

O BDD complementa isso colmatando a lacuna entre os requisitos de negócios e os testes de aceitação de nível superior. É a satisfação do conjunto do BDD que esclareia o processo de desenvolvimento e que determina quando o produto como um todo foi entregue adequadamente.

    
por 06.04.2014 / 23:46
fonte
19

As diferenças entre o TDD e o BDD são sutis e se resumem à linguagem . Os testes do BDD costumam ser escritos da seguinte forma:

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

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

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

Se você enquadrar o teste em termos de comportamento , isso ajudará a definir a responsabilidade da classe e levará a um melhor design (pelo menos de acordo com os BDD's). O BDD às vezes se concentra em especificações executáveis que seus especialistas / clientes de domínio podem entender.

O BDD também está mais associado com o que Martin Fowler chama de testes "fora-de-dentro" ou "mockistas" , ao contrário para verificação baseada em estado.

    
por 15.02.2012 / 19:49
fonte
12

Desde que a minha última resposta não foi muito bem sucedida, vou tentar uma abordagem muito simples.

  • Behaviour Driven Development é um subconjunto de Test Driven Development
  • TDD foca em cada teste unitário para cada função, não importa o que faça. BDD foca em software que importa
  • Idiom . TDD resolve para os testes, BDD impõe narração de histórias formato

Exemplos de JavaScript

Testes de unidade em jasmim ( BDD )

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

Testes de unidade no jsUnity ( TDD )

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

Aqui estão algumas bibliotecas Python que ajudam a criar mais BDD como testes com as estruturas do teste unitário:

  • Lettuce : pepino para python
  • HamCrest
por 14.01.2014 / 05:33
fonte
4

O BDD adiciona mais um nível de abstração aos testes. O código de nível mais alto (geralmente em txt) descreve o que o sistema testa, o código de nível inferior descreve como o testa. Portanto, uma estrutura do BDD pode usar um framework TDD no código de nível inferior.

Isso ajuda muito ficando DRY. Por TDD você pode facilmente acabar com testes "molhados" contendo muita duplicação de código, o que os torna fáceis de quebrar refatorando o código e os testes com ele. Pelo BDD você tem que modificar apenas o nível de abstração mais baixo refatorando o código, então se a especificação não mudar, o código de nível mais alto não mudará.

Entre. isto é simples Clean Code, normalmente é suficiente ler o material de alto nível de abstração para entender o que ele faz, e se aprofundar no código de teste de nível de abstração mais baixo somente se você realmente precisar dele. Isso torna o código (de teste) mais fácil de entender em geral.

Um mau exemplo (porque é muito simples):

estilo TDD jasmim

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);
    });
});

estilo BDD jasmim-pepino

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));
    });

implementação

calculator.js

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

Agora, se eu renomear a função add() para sum() , terei que alterar o código TDD em 2 locais, enquanto o código BDD estará em um único local no arquivo etapas . Ofc. adicionar mais um nível de abstração requer mais código ...

    
por 21.05.2015 / 23:07
fonte
2

Só para deixar isso confuso, perceba que muitas pessoas agora associam o BDD ao pepino. Eles consideram qualquer teste que você escrever usando sintaxe derivada de pepino para ser uma verificação de BDD, e qualquer coisa escrita usando uma estrutura de teste de unidade (junit, unittest.py, etc) para ser TDD.

Está errado. A mídia não define a mensagem neste caso. Nem o uso de zombarias (IMHO).

A principal diferença já foi dada: o BDD é uma técnica baseada em recursos, usando linguagem onipresente e uma abordagem de fora para dentro. Nós escrevemos especificações (que mais tarde serão executadas como testes) para uma história ou uma fatia de uma história. A pequenez e a concretude importam, e é uma "explicação pelo exemplo" do que é necessário / esperado deste aspecto da história.

As especificações do BDD são frequentemente escritas em uma linguagem semelhante a um pepino, se as pessoas que precisam especificar o recurso não lerem / escrevem código (casos freqüentes em organizações maiores ou onde um cliente real faz parte da equipe). Caso contrário, pepino-ese não é necessário. Estes tendem a ser a saída do famoso encontro de 3 Amigos: business, test, dev todos fazem isso juntos. Ao usar uma estrutura de BDD (fit, cucumber, etc), o teste é mais lento e exige um pouco mais de infraestrutura, por isso, mantemos esses relativamente escassos - alguns por história.

TDD é usado ao criar código. O propósito é dar uma progressão ordenada de escrever o recurso com muitas oportunidades de refatoração e com uma confiança razoável de que você não está quebrando nada acidentalmente enquanto escreve o novo código. Não é necessário descrever recursos do sistema, apenas de um método (ou alguns com um efeito comum). Ninguém, a não ser os desenvolvedores, precisa ler os testes escritos aqui, mas eles têm que correr rápido e isolar os erros. Eles correm loucamente rápido porque pode haver muitos testes por função de membro de classe ('método').

Se você fizer o BDD na camada externa, ainda será útil fazer o TDD no loop interno devido à refatoração e à capacidade de detectar e evitar erros mais rapidamente.

Nenhuma prova de correção para um sistema grande. Nenhum dos dois substitui os testes de caneta e perf. Não garante segurança de rosca. Os testes ajudam no desenvolvimento, não garantem a perfeita impermeabilidade.

    
por 22.05.2015 / 19:07
fonte

Tags