¿Cuál es la diferencia entre escribir casos de prueba para BDD y TDD? [duplicar]

243

He estado aprendiendo a escribir casos de prueba para BDD (Behavior Driven Development) usando el flujo de especificaciones. Si escribo pruebas completas con BDD, ¿es necesario escribir la prueba TDD (Test Driven Development) por separado? ¿Es necesario escribir los casos de prueba para TDD y BDD por separado, o son efectivamente lo mismo?

Me parece que ambos son iguales, la única diferencia es que los desarrolladores y evaluadores no pueden entender los casos de prueba de BDD.

    
pregunta arjun 15.02.2012 - 17:59
fuente

8 respuestas

212

La diferencia entre BDD y TDD es que BDD comienza con una B y TDD comienza con una T. Pero en serio, el gotcha con TDD es que muchos desarrolladores se centraron en el "Cómo" al escribir sus pruebas unitarias, por lo que terminaron con pruebas muy frágiles que no hicieron más que confirmar que el sistema hace lo que hace.

BDD proporciona un nuevo vocabulario y, por lo tanto, se enfoca en escribir una prueba de unidad. Básicamente es un enfoque basado en características para TDD.

    
respondido por el Michael Brown 15.02.2012 - 20:06
fuente
50

Behavior Driven Development es una extensión / revisión de Test Driven Development. Su propósito es ayudar a las personas que diseñan el sistema (es decir, los desarrolladores) a identificar las pruebas apropiadas para escribir, es decir, las pruebas que reflejan el comportamiento deseado por las partes interesadas. El efecto termina siendo el mismo: desarrolle la prueba y luego desarrolle el código / sistema que pasa la prueba. La esperanza en BDD es que las pruebas sean realmente útiles para mostrar que el sistema cumple con los requisitos.

ACTUALIZAR

Las unidades de código (métodos individuales) pueden ser demasiado granulares para representar el comportamiento representado por las pruebas de comportamiento, pero aún así debe probarlas con pruebas unitarias para garantizar que funcionen adecuadamente. Si esto es lo que quiere decir con las pruebas "TDD", entonces sí, todavía las necesita.

    
respondido por el Matthew Flynn 15.02.2012 - 18:09
fuente
25

BDD utiliza algo llamado "Lenguaje Ubicuo", un cuerpo de conocimiento que puede ser comprendido tanto por el desarrollador como por el cliente. Este lenguaje ubicuo se usa para dar forma y desarrollar los requisitos y las pruebas necesarias, a nivel de la comprensión del cliente.

Dentro de los límites de los requisitos y las pruebas dictadas por BDD, utilizará un TDD "normal" para desarrollar el software. Las pruebas unitarias así creadas servirán como un conjunto de pruebas para su código de implementación, mientras que las pruebas BDD funcionarán más o menos como pruebas de aceptación para el cliente.

    
respondido por el Robert Harvey 15.02.2012 - 18:07
fuente
20

En mi experiencia, el mayor problema con TDD es la " T ". Hace que la persona laica (administradores, evaluadores, desarrolladores que no son TDD) la equipare en sus mentes con la fase tradicional de "Prueba" de post-desarrollo de un estilo de cascada. Eso es algo que cualquiera puede entender.

El problema con el que muchos luchan es que TDD es para desarrolladores, no para probadores. La correcta TDD no es principalmente una estrategia de prueba o una herramienta de prueba de aceptación, sino una técnica que impulsa un buen diseño de software desde el principio: clases pequeñas y poco acopladas, interfaces claras y bien definidas y código continuamente limpiado a través de la refactorización en curso. Refactorización que se realiza de forma rutinaria, frecuente y desde una posición de confianza.

Que termine con un conjunto de pruebas completo que puede formar parte de su CI / proceso de construcción es una ventaja, no el objetivo.

BDD complementa esto al cerrar la brecha entre los requisitos comerciales y las pruebas de aceptación de nivel superior. Es lo que satisface a la suite BDD el alcance del proceso de desarrollo y el que determina cuándo se ha entregado adecuadamente el producto en su totalidad.

    
respondido por el sim303 06.04.2014 - 23:46
fuente
19

Las diferencias entre TDD y BDD son sutiles y en su mayoría se reducen a idioma . las pruebas de BDD a menudo se escriben en el siguiente formulario:

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

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

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

Si encuadra la prueba en términos de comportamiento , esto ayuda a que la clase sea responsable y lleva a un mejor diseño (al menos de acuerdo con los BDD). BDD a veces se centra en especificaciones ejecutables que los expertos / clientes de su dominio pueden entender.

BDD también está más asociado con lo que Martin Fowler llama pruebas de "afuera hacia adentro" o "mockist" , en contraposición a a la verificación basada en el estado.

    
respondido por el Garrett Hall 15.02.2012 - 19:49
fuente
12

Como mi última respuesta no fue muy exitosa, intentaré un enfoque muy directo.

  • Behaviour Driven Development es un subconjunto de Test Driven Development
  • TDD se enfoca en cada una de las pruebas de unidad para cada función, no importa lo que haga. BDD se enfoca en el software que importa
  • Idiom . TDD se conforma con las pruebas, BDD aplica el formato narración de historias

Ejemplos de JavaScript

Pruebas de unidad en jazmín ( BDD )

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

Pruebas unitarias en jsUnity ( TDD )

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

Aquí hay algunas bibliotecas de Python que ayudan a crear más BDD como pruebas con marcos de unittest:

  • Lechuga : Pepino para pitón
  • HamCrest
respondido por el percebus 14.01.2014 - 05:33
fuente
4

BDD agrega un nivel más de abstracción a las pruebas. El código de nivel superior (generalmente en txt) describe lo que el sistema prueba, el código de nivel inferior describe cómo lo prueba. Por lo tanto, un marco BDD puede usar un marco TDD en el código de nivel inferior.

Esto ayuda mucho manteniéndose SECO. Por TDD, puede terminar fácilmente con las pruebas "húmedas" que contienen una gran cantidad de duplicación de código, lo que facilita su ruptura al refactorizar el código y las pruebas con él. Por BDD, solo tiene que modificar el nivel de abstracción inferior mediante la refactorización del código, por lo que si la especificación no cambia, el código de nivel superior no cambiará.

Por cierto. Este es un Código limpio simple, por lo general, es suficiente leer las cosas de alto nivel de abstracción para comprender lo que hace y profundizar en el código de prueba de nivel de abstracción más bajo solo si realmente lo necesita. Esto hace que el código (de prueba) sea más fácil de entender en general.

Un mal ejemplo (porque es demasiado simple):

estilo TDD de jazmín

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 de jazmín y 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));
    });

implementacion

calculator.js

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

Ahora, si cambio el nombre de la función add() a sum() , tengo que cambiar el código TDD en 2 lugares, mientras que el código BDD solo aparece en un solo lugar en el archivo steps . De c. agregar un nivel de abstracción más requiere más código ...

    
respondido por el inf3rno 21.05.2015 - 23:07
fuente
2

Solo para mantenerlo confuso, se da cuenta de que muchas personas ahora asocian BDD con pepino. Consideran que cualquier prueba que escriba usando la sintaxis derivada de gherkin es una verificación BDD, y cualquier cosa escrita usando un marco de prueba de unidad (junit, unittest.py, etc.) será TDD.

Está mal. El medio no define el mensaje en este caso. Tampoco el uso de mocks (IMHO).

La principal diferencia ya estaba dada: la BDD es una técnica basada en características, que utiliza un lenguaje ubicuo y un enfoque externo. Escribimos especificaciones (que luego se ejecutarán como pruebas) para una historia o un fragmento de una historia. La pequeñez y la concreción son importantes, y es una "explicación con el ejemplo" de lo que se necesita / espera de este aspecto de la historia.

Las especificaciones de BDD se escriben con frecuencia en un lenguaje similar al pepinillo si las personas que necesitan especificar la función no todas son de código de lectura / escritura (casos frecuentes en organizaciones más grandes o donde un cliente real es parte del equipo). De lo contrario, gherkin-ese no es necesario. Estos tienden a ser el resultado de la famosa reunión de 3 Amigos: negocios, pruebas, todos los desarrolladores hacen esto juntos. Cuando se usa un marco BDD (ajuste, pepino, etc.) la prueba es más lenta y requiere un poco más de infraestructura, por lo que mantenemos estos relativamente escasos, algunos por historia.

TDD se utiliza al crear código. El propósito es dar una progresión ordenada de escritura de la función con muchas oportunidades para refactorizar y con una confianza razonable de que no estás rompiendo nada accidentalmente al escribir el nuevo código. No es necesario describir las características del sistema, solo un método (o unos pocos con un efecto común). Nadie más que los desarrolladores necesitan leer las pruebas escritas aquí, pero tienen que correr locamente rápido y aislar los errores. Se vuelven locos rápido porque puede haber muchas pruebas por función de miembro de clase ("método").

Si realiza BDD en la capa externa, aún es útil hacer TDD en el bucle interno debido a la refactorización y la capacidad de detectar y evitar errores más rápidamente.

Tampoco hay pruebas de corrección para un sistema grande. Tampoco reemplaza la prueba de pluma y perf. Tampoco garantiza la seguridad del hilo. Las pruebas son una ayuda en el desarrollo, no son garantías de una perfecta prueba de errores.

    
respondido por el tottinge 22.05.2015 - 19:07
fuente

Lea otras preguntas en las etiquetas