¿Cómo usar las pruebas unitarias cuando se usa BDD?

17

Estoy tratando de entender BDD. He leído algunos artículos y, como entendí, BDD es "el siguiente paso" de TDD. Digo eso porque encuentro que ambos son muy similares, y como pude leer en este artículo , BDD nació como una mejora de TDD. Genial, me gusta mucho la idea.

Hay un punto práctico que no entiendo, pensé: hay un archivo .feature en el que el BA escribirá todo el comportamiento esperado en el que tendría el sistema. Como BA, no tiene idea de cómo se construye el sistema, por lo que escribiremos algo como esto:

+ Escenario 1: la cuenta está en crédito +

Dado que la cuenta está en crédito

Y la tarjeta es valida

Y el dispensador contiene efectivo

Cuando el cliente solicita efectivo

Luego asegúrese de que la cuenta sea debitada y asegúrese de que se distribuya efectivo

Y asegúrese de devolver la tarjeta

Ok, esto es genial, pero hay muchas partes del sistema que colaborarán para que pueda suceder (piense en obj de cuenta, obj de dispensador, obj de cliente, etc.). Para mí, esto parece una prueba de integración.

Me gustaría tener pruebas unitarias. ¿Cómo pruebo el código que verifica si el dispensador tiene dinero? ¿O que se dispensa el efectivo? ¿O que se debita la cuenta cuando sea necesario? ¿Cómo puedo mezclar pruebas unitarias con pruebas "BA Creado"?

JSBach
fuente
Para eso están los simulacros y los trozos: para aislar las partes bajo pruebas.
Robert Harvey
Lo siento, no lo entiendo. ¿Quieres decir que debo burlarme del dispensador? ¿Cómo lo probaría?
JSBach
Cuando prueba el dispensador, se burla de la cuenta, la tarjeta y el cliente.
Robert Harvey
3
¿Por qué quiere mezclar pruebas unitarias y "pruebas creadas por BA"? Use TDD como técnica para crear pruebas unitarias para partes individuales de su software y agregue pruebas adicionales para probar los requisitos desde el punto de vista de BA (llame a las últimas pruebas de integración, si lo desea). ¿Dónde ves una contradicción?
Doc Brown
@DocBrown: Por "emerger naturalmente", quiero decir que algunos TDD creen que un diseño de software surgirá naturalmente de las pruebas unitarias a medida que "refactorice rojo-verde". La conversación de chat en curso sobre esta pregunta se lleva a cabo en The Whiteboard .
Robert Harvey

Respuestas:

27

El desarrollo basado en el comportamiento y el desarrollo basado en la prueba son complementarios, pero no se reemplazan entre sí.

La forma en que la aplicación "se comporta" se describe en las Pruebas de aceptación, que según BDD serían las características y escenarios escritos en Pepino.

Los detalles esenciales de cómo funciona cada componente pequeño se describen en Pruebas unitarias. Los resultados de las pruebas unitarias respaldan los escenarios que escribe en Pepino.

Imagine el proceso para construir un automóvil.

Primero, el equipo de producto presenta sus ideas y, finalmente, las reduce a escenarios de uso:

Scenario: Starting the car
    Given I am standing in front of the drivers door
    When I open the door
    Then the door should lift up DeLorean-style (yeah, baby!)
    When I get into the car
    And turn the key
    Then the engine roars to life

Sé que este escenario suena un poco tonto, pero es un requisito muy alto, centrado en el producto y el usuario final. Solo abrir la puerta, girar la llave y arrancar el motor implica MUCHOS componentes diferentes trabajando juntos. Esta prueba no es suficiente para asegurarse de que el vehículo funcione correctamente. Debe probar el motor de arranque, la batería, el alternador, la llave, el interruptor de encendido --- y la lista continúa --- solo para subir al automóvil y arrancarlo. Cada uno de esos componentes necesita sus propias pruebas.

El escenario anterior es una prueba de "panorama general". Cada componente del vehículo necesita pruebas de "Imagen pequeña" para asegurarse de que funcionan correctamente dentro del conjunto.

La creación y prueba de software es igual en muchos aspectos. Diseñas de arriba hacia abajo, luego construyes de abajo hacia arriba. ¿Por qué tener una puerta que se levanta si ni siquiera puedes arrancar el motor? ¿Por qué tener un motor de arranque si no tienes batería?

Su equipo de producto elaborará las Pruebas de aceptación y las desarrollará en Pepino. Esto te da la "gran imagen". Ahora le corresponde al equipo de ingeniería diseñar los componentes adecuados y cómo interactúan, luego probar cada uno por separado: estas son sus pruebas unitarias.

Una vez que pasan las Pruebas de Unidad, comience a implementar los escenarios de Pepino. Una vez que pasan, ha entregado lo que ha pedido el equipo del producto.

Greg Burghardt
fuente
¿Hay alguna manera de vincular esas pruebas de "Imagen general" con las pruebas de "Imagen pequeña"? Quiero decir, cuando las características cambian oficialmente (por ejemplo, un escenario de pepino cambiante), ¿hay alguna forma de asignar ese cambio a las pruebas de gama baja (por ejemplo, pruebas de junit que son para ese escenario de pepino en particular)?
Srikanth
Puede compartir métodos de ayuda y aserciones personalizadas entre las pruebas de "imagen general" y "imagen pequeña", pero lo más probable es que impliquen una configuración diferente para probar unidades de código específicas.
Nick McCurdy
[...] que según BDD serían las Características y Escenarios escritos en Pepino. Estás combinando principios y herramientas.
jub0bs
Bueno, está bien, la redacción está un poco fuera de lugar, pero el punto es que el comportamiento de una aplicación se captura en las características y escenarios.
Greg Burghardt
9

Estoy tratando de entender BDD. He leído algunos artículos y, como entendí, BDD es "el siguiente paso" de TDD. Digo eso porque encuentro que ambos son muy similares, y como pude leer en este artículo, BDD nació como una mejora de TDD.

En realidad, no, BDD no es "el siguiente paso" de TDD. que es TDD. O más precisamente, es una reformulación de TDD.

Los creadores de BDD notaron que el principal obstáculo para comprender que TDD no se trata de pruebas sino de especificación de comportamiento es que toda la terminología de TDD se trata de pruebas y no de especificación de comportamiento. Es como tratar de no pensar en un elefante rosado cuando alguien te dice "trata de no pensar en un elefante rosado", excepto con la complicación adicional de estar en una habitación llena de elefantes rosados ​​y un chico que constantemente grita "elefante rosa, rosa". elefante, elefante rosa "en tu oído.

Entonces, reformularon TDD en términos de especificación de comportamiento. "Pruebas" y "casos de prueba" son ahora "ejemplos", "unidades" son "comportamientos", "aserciones" son "expectativas", etc.

Sin embargo, la metodología sigue siendo la misma. Comienzas con una prueba de aceptación (me refiero a "función"), acercas a una prueba unitaria (me refiero a "ejemplo"), alejas, etc.

Me gustaría tener pruebas unitarias. ¿Cómo pruebo el código que verifica si el dispensador tiene dinero? ¿O que se dispensa el efectivo? ¿O que se debita la cuenta cuando sea necesario? ¿Cómo puedo mezclar pruebas unitarias con pruebas "BA Creado"?

De la misma manera que lo hace en TDD. Puede escribir sus características y sus ejemplos en diferentes marcos (por ejemplo, Cucumber y RSpec) o incluso en diferentes lenguajes (por ejemplo, escribir ejemplos para un proyecto C en C y características en FIT / Fitnesse), puede usar un marco de características único para ambos ( por ejemplo, escribir ejemplos y características en Pepino) o puede usar el marco de ejemplos individuales para ambos (por ejemplo, escribir ambos en RSpec). Ni siquiera tiene que usar un marco en absoluto.

Un ejemplo de TDD-done-right (que es idéntico a BDD) usando solo un marco es JUnit, que contiene una mezcla de pruebas unitarias (ejemplos) y pruebas funcionales / de integración (características), todas escritas en JUnit.

Creo que Kent Beck llama a esto "acercamiento". Comience a alto nivel, luego "acerque" los detalles y luego retroceda nuevamente.

Jörg W Mittag
fuente
1

Descargo de responsabilidad: no soy un experto en BDD, pero trato de darle mi punto de vista sobre el artículo al que se vinculó.

TDD es una técnica de implementación: primero escribe una prueba, luego implementa el método, ejecuta su prueba, refactoriza y agrega más pruebas para el mismo método o para un nuevo método. TDD en realidad no define ninguna regla sobre cómo elegir los nombres de clase o método, eso depende de usted. TDD tampoco le dice "cuando haya terminado".

Por lo tanto, cada vez que escriba una prueba para un nuevo método, debe elegir el nombre de un método, y ese es el punto en el que entra BDD. Al elegir los nombres de los métodos utilizando los términos comerciales del escenario anterior, y al elegirlos de una manera que describa el comportamiento de tu clase, estás haciendo BDD. Cada vez que se pregunte "¿tengo que agregar más pruebas", puede ver los escenarios ofrecidos por su BA y verificar si ha implementado todas las partes necesarias por completo. De lo contrario, deberá agregar más pruebas.

El autor del artículo también sugiere utilizar un esquema de nomenclatura más relacionado con el comportamiento al elegir los nombres de sus pruebas, por eso sugiere reemplazar JUnit por una herramienta que no se base en un esquema de nomenclatura donde cada caso de prueba tiene que comenzar con el nombre "prueba". Aunque no conozco a JBehave, creo que esa es la principal diferencia entre esa herramienta y Junit.

Además, los escenarios de BDD también serán un plan para las pruebas de integración, que normalmente agregará después haber desarrollado los nombres de los métodos por TDD y después de haber agregado una cantidad razonable de pruebas unitarias.

Entonces, según tengo entendido, TDD es un instrumento que puede usar como parte de BDD, y BDD lo ayuda a escribir las pruebas correctas y darles mejores nombres.

Doc Brown
fuente
Como punto rápido, Junit admite nombrar cualquier cosa a tus pruebas; solo tiene que usar una anotación @Test. Sin embargo, puede que no lo haya hecho en 2003.
soru
@soru En 2003, efectivamente hizo cumplir la palabra "prueba".
Lunivore
El autor del artículo es Dan North, quien se le ocurrió el concepto en primer lugar. Una de las cosas que notó es que la palabra "prueba" nos hace pasar a probar nuestra implementación (dominio de la solución) mientras que, en realidad, explorar y definir las pruebas realmente debería mantenernos en el dominio del problema. Dan ha descrito a BDD como "lo que TDD estaba destinado a ser". Lea esto para obtener más información: dannorth.net/2012/05/31/bdd-is-like-tdd-if
Lunivore