¿Qué es BDD y por qué no es solo otra moda pasajera?
\n\n¿Alguna vez ha escrito código que funciona perfectamente desde el punto de vista del compilador, pero que no hace lo que el negocio necesita? ¿Le resulta familiar cuando un gerente mira una función terminada y dice: "Bueno, pensé que sería diferente"? Si es así, bienvenido al mundo de BDD (Behaviour-Driven Development) — desarrollo guiado por el comportamiento. No es solo una metodología, sino un puente entre "quiero que el botón sea verde" y "aquí hay una prueba que falla si el botón no es verde".
\n\nA diferencia del TDD (Test-Driven Development) clásico, donde pensamos en las pruebas como verificación de funciones, BDD se centra en el comportamiento del sistema desde la perspectiva del usuario. En el contexto de C++, esto es especialmente valioso: el lenguaje es complejo, los proyectos son enormes y reescribir la lógica después de un malentendido con el cliente es un placer costoso. BDD en C++ ayuda a matar dos pájaros de un tiro: obtener documentación que incluso un gerente de proyecto pueda entender y un conjunto de pruebas automáticas que eviten que la lógica de negocio se rompa.
\n\nEn este artículo, analizaremos cómo implementar behaviour-driven development en un proyecto real de C++. Sin rodeos, con código y técnicas concretas.
\n\nFundamentos de BDD: el lenguaje Gherkin y su papel en C++
\n\nEl corazón de BDD son los escenarios escritos en el lenguaje Gherkin. Se ven más o menos así:
\n\nFeature: Transferencia de fondos entre cuentas\n Scenario: Transferencia exitosa con saldo suficiente\n Given el usuario tiene una cuenta A con un saldo de 1000 rublos\n And el usuario tiene una cuenta B con un saldo de 0 rublos\n When el usuario transfiere 500 rublos de la cuenta A a la cuenta B\n Then el saldo de la cuenta A se convierte en 500 rublos\n And el saldo de la cuenta B se convierte en 500 rublos\n\nSí, esto no es C++. Pero ahí está la magia: el escenario está escrito en lenguaje humano y luego se "vincula" al código C++ real a través de pasos (steps). Cada línea Given, When, Then se convierte en una función que invoca sus clases y verifica los resultados.
Para C++, existen varios frameworks que pueden trabajar con Gherkin. Los más populares son:
\n\n- \n
- Catch2 con estilo BDD — ligero, integrado en Catch2, no requiere analizadores externos. \n
- Cucumber-CPP — una implementación completa de Cucumber para C++, analiza archivos .feature directamente. \n
- Boost.Test — también admite sintaxis similar a BDD, pero es menos flexible. \n
Personalmente, recomiendo comenzar con Catch2: ya está presente en el 90% de los proyectos C++ y para BDD no es necesario instalar nada adicional. Si el proyecto es grande y se necesita integración con analistas de negocio, elija Cucumber-CPP.
\n\nBDD con Catch2: escribiendo escenarios directamente en el código
\n\nCatch2 proporciona las macros SCENARIO, GIVEN, WHEN, THEN y AND_WHEN/AND_THEN. No es Gherkin puro, pero el estilo es muy cercano. Escribamos una prueba para una cuenta bancaria simple.
Primero, la clase de la cuenta:
\n\n// account.h\n#pragma once\n#include <string>\n#include <stdexcept>\n\nclass Account {\npublic:\n explicit Account(std::string owner, double initial_balance = 0.0)\n : owner_(std::move(owner)), balance_(initial_balance) {}\n\n void deposit(double amount) {\n if (amount <= 0) throw std::invalid_argument("Amount must be positive");\n balance_ += amount;\n }\n\n void withdraw(double amount) {\n if (amount > balance_) throw std::runtime_error("Insufficient funds");\n if (amount <= 0) throw std::invalid_argument("Amount must be positive");\n balance_ -= amount;\n }\n\n double balance() const { return balance_; }\n const std::string& owner() const { return owner_; }\n\nprivate:\n std::string owner_;\n double balance_ = 0.0;\n};\n\nY ahora, la prueba BDD usando Catch2:
\n\n// tes