🧩 BDD (Behavior-Driven Development)

📘 Conceptos

  • Behavior-Driven Development
    • Extensión de TDD - Test Driven Development centrada en el comportamiento del sistema.
    • Permite comunicación clara entre desarrolladores, QA y negocio.
  • Lenguaje Específico de Dominio (DSL)
    • Lenguaje legible por humanos para definir comportamientos.
    • Ejemplo: Gherkin.
  • Gherkin
    • Sintaxis estándar para definir escenarios BDD.
    • Palabras clave: Feature, Scenario, Given, When, Then, And, But.
    • Estructura básica: given, when, them - practica bdd
      • Ejemplo práctico:
  • logica de negocio
    • Los tests se escriben desde la perspectiva del comportamiento esperado.
    • Permite validar funcionalidades de extremo a extremo y alinearlas con los objetivos del negocio.
    • Los escenarios describen qué se espera del sistema, no cómo se implementa.
    • El código se escribe después, validando ese comportamiento.
Feature: Login de usuario
Scenario: Usuario inicia sesión correctamente
	Given el usuario existe con email "user@test.com" y password "1234"
	When el usuario envía una solicitud POST a "/login"
	Then el sistema responde con código 200 y un token JWT

🧾 Documentación y referencias

  • ¿Qué es BDD (Behavior Driven Development)-
  • BDD Testing. ¿Cómo funciona el Behavior Driven Development-

🛠️ Tools BDD

  • Behat
    • Behat Documentation — Behat documentation-guides.html
    • Compatible con Gherkin.
  • SpecFlow
    • Integración con .NET y Visual Studio.
    • Permite definir escenarios en Gherkin.
  • Behave
    • Framework BDD para Python.
    • Compatible con Selenium y pruebas automatizadas.
  • cucumber
    • Framework multiplataforma (JS, Java, Ruby, etc.).
    • Ejecuta escenarios definidos en Gherkin enlazados a código con step definitions.

🔄 Buenas prácticas BDD

  • Escribir los escenarios antes de implementar la funcionalidad.
  • Involucrar Testing, QA y desarrollo en la definición de escenarios.
  • Mantener el DSL consistente y legible para toda la organización.
  • Priorizar features críticas y flujos de negocio.
  • Reutilizar pasos comunes con step definitions.
  • Integrar BDD en pipelines de CI/CD para asegurar validación continua de comportamiento.

🧠 Flujo general BDD

  1. Definir el comportamiento esperado en lenguaje Gherkin.
  2. Implementar los step definitions que conectan los pasos con código real.
  3. Ejecutar los tests con una herramienta BDD (Cucumber, Behat, etc.).
  4. Integrar los resultados en el pipeline CICD para validar continuamente.

Buenas prácticas BDD

  • Iniciar cada feature con una historia de usuario clara.
  • Escribir escenarios legibles y sin lógica técnica.
  • Evitar repetir pasos; usar steps reutilizables.
  • Mantener una nomenclatura coherente (nombres naturales y consistentes).
  • Automatizar la ejecución en pipelines CI/CD.
  • Integrar herramientas de reporting (Allure, Cucumber Reports, etc.).
  • Usar mocks o stubs para componentes externos cuando sea necesario.
  • Documentar escenarios fallidos con capturas o logs de ejecución.

💻 Ejemplos Prácticos de BDD

🥒 Ejemplo Cucumber (JavaScript)

Feature: Autenticación
	Scenario: Login exitoso
		Given el usuario "admin" con contraseña "1234"
		When intenta iniciar sesión
		Then el sistema muestra "Bienvenido, admin"
import { Given, When, Then } from "@cucumber/cucumber";
import assert from "assert";

let user;

Given('el usuario {string} con contraseña {string}', function (username, password) {
	user = { username, password };
});

When('intenta iniciar sesión', function () {
	this.result = user.password === "1234" ? "Bienvenido, admin" : "Error";
});

Then('el sistema muestra {string}', function (message) {
	assert.strictEqual(this.result, message);
});

🐍 Ejemplo Behave (Python)

Feature: Registro de usuario
	Scenario: Crear nuevo usuario
		Given un formulario válido
		When el usuario envía sus datos
		Then el sistema responde con "Usuario creado correctamente"
# steps/registro_steps.py
from behave import given, when, then

@given('un formulario válido')
def step_given_form(context):
	context.formulario = {"nombre": "Carlos", "email": "test@test.com"}

@when('el usuario envía sus datos')
def step_when_submit(context):
	context.resultado = "Usuario creado correctamente"

@then('el sistema responde con "{mensaje}"')
def step_then_response(context, mensaje):
	assert context.resultado == mensaje

🧩 Ejemplo SpecFlow (.NET / C#)

Feature: Calculadora
	Scenario: Sumar dos números
		Given el primer número es 5
		And el segundo número es 7
		When los sumo
		Then el resultado debe ser 12
using TechTalk.SpecFlow;
using NUnit.Framework;

[Binding]
public class CalculadoraSteps
{
	private int num1, num2, resultado;

	[Given(@"el primer número es (.*)")]
	public void DadoElPrimerNumeroEs(int n) => num1 = n;

	[Given(@"el segundo número es (.*)")]
	public void DadoElSegundoNumeroEs(int n) => num2 = n;

	[When(@"los sumo")]
	public void CuandoLosSumo() => resultado = num1 + num2;

	[Then(@"el resultado debe ser (.*)")]
	public void EntoncesElResultadoDebeSer(int esperado)
		=> Assert.AreEqual(esperado, resultado);
}

🧱 Ejemplo Behat (PHP)

Feature: API de usuarios
	Scenario: Consultar datos del usuario
		Given existe un usuario con ID 1
		When hago una petición GET a "/users/1"
		Then la respuesta contiene "nombre"
<?php
use Behat\Behat\Context\Context;
use PHPUnit\Framework\Assert;

class UserContext implements Context
{
	private $response;

	/** @Given existe un usuario con ID :id */
	public function existeUsuario($id)
	{
		// Simulación de existencia de usuario
	}

	/** @When hago una petición GET a :endpoint */
	public function hagoPeticionGET($endpoint)
	{
		$this->response = ["nombre" => "Carlos"];
	}

	/** @Then la respuesta contiene :campo */
	public function respuestaContiene($campo)
	{
		Assert::assertArrayHasKey($campo, $this->response);
	}
}