EARS + Gherkin
EARS + Gherkin
EARS y Gherkin trabajan en capas distintas pero complementarias:
| Capa | Lenguaje | Pregunta que responde |
|---|---|---|
| Requisito | EARS | ¿Qué debe hacer el sistema? |
| Escenario | Gherkin | ¿Cómo verificamos que lo hace? |
Un requisito EARS típico se convierte en uno o varios escenarios Gherkin. EARS es el contrato, Gherkin son los ejemplos ejecutables del contrato.
Mapeo conceptual
flowchart LR
REQ[Requisito EARS<br/>When/While/Where/If] --> Scenario[Scenario Gherkin<br/>Given/When/Then]
REQ -.->|disparador| ScenWhen[When del Gherkin]
REQ -.->|sujeto + respuesta| ScenThen[Then del Gherkin]
REQ -.->|estado/feature| ScenGiven[Given del Gherkin]
Reglas de derivación:
Where/Whilede EARS →Givende Gherkin (preconditions)When/Ifde EARS →Whende Gherkin (action o stimulus)- “shall
” de EARS → Thende Gherkin (expected outcome)
Ejemplo 1: derivación 1:1
EARS:
REQ-AUTH-001: When the user submits valid credentials to /auth/login, the auth service shall return HTTP 200 with a JWT valid for 24 hours.
Gherkin derivado:
Feature: Login con credenciales válidas
Scenario: Usuario existente con credenciales correctas obtiene un JWT
Given un usuario registrado con email "[email protected]" y password "secret123"
When envío POST /auth/login con email "[email protected]" y password "secret123"
Then la respuesta tiene status 200
And el cuerpo contiene un campo "token" con un JWT
And el JWT expira en 24 horas
Un requisito → un escenario. Trazabilidad directa.
Ejemplo 2: un EARS, múltiples escenarios
EARS:
REQ-AUTH-002: If the credentials are invalid, then the auth service shall return HTTP 401 with body { "error": "invalid_credentials" } indistinguishably between "user not found" and "wrong password".
Gherkin derivado (dos escenarios cubren el mismo REQ):
Feature: Login con credenciales inválidas
Scenario: Usuario inexistente
Given que no existe un usuario con email "[email protected]"
When envío POST /auth/login con email "[email protected]" y password "anything"
Then la respuesta tiene status 401
And el cuerpo es { "error": "invalid_credentials" }
Scenario: Contraseña incorrecta para usuario existente
Given un usuario registrado con email "[email protected]" y password "secret123"
When envío POST /auth/login con email "[email protected]" y password "wrong-password"
Then la respuesta tiene status 401
And el cuerpo es { "error": "invalid_credentials" }
Scenario: Las respuestas son indistinguibles entre usuario inexistente y contraseña incorrecta
Given que no existe un usuario con email "[email protected]"
And un usuario registrado con email "[email protected]" y password "secret123"
When envío POST /auth/login con email "[email protected]" y password "anything"
And capturo la respuesta como R1
When envío POST /auth/login con email "[email protected]" y password "wrong-password"
And capturo la respuesta como R2
Then R1.status es igual a R2.status
And R1.body es igual a R2.body
El REQ se cubre con 3 escenarios — uno por caso de borde.
Ejemplo 3: Scenario Outline para Where
Los requisitos con Where (optional feature) a menudo dan lugar a Scenario Outlines:
EARS:
REQ-EXPORT-001: Where the user has subscription <plan>, when the user requests an export, the service shall allow files up to <max_size> MB.
Gherkin derivado:
Feature: Tamaño máximo de export según plan
Scenario Outline: Límite de export por plan
Given un usuario con subscription "<plan>"
When solicito export de "<size>" MB
Then la respuesta tiene status "<expected_status>"
Examples:
| plan | size | expected_status |
| free | 10 | 200 |
| free | 50 | 413 |
| pro | 50 | 200 |
| pro | 200 | 413 |
| premium | 500 | 200 |
| premium | 2000 | 413 |
Una sola tabla cubre todas las combinaciones del requisito.
Trazabilidad EARS ↔ Gherkin
Agregá el REQ-ID como tag en el feature/scenario:
Feature: Autenticación
@REQ-AUTH-001
Scenario: Usuario obtiene JWT con credenciales válidas
Given ...
@REQ-AUTH-002
Scenario: Credenciales inválidas devuelven 401
Given ...
Esto permite reportes automatizados de cobertura de requisitos — qué REQ tienen al menos un escenario, cuáles no.
EARS para describir el comportamiento del sistema; Gherkin para describir ejemplos
Recordá la diferencia:
- EARS describe categoría (“if invalid credentials”)
- Gherkin describe ejemplos concretos (“email=‘[email protected]’, password=‘anything’”)
Por eso un EARS puede dar lugar a varios Gherkin: el sistema dice “rechazá credenciales inválidas”, los escenarios dicen “acá hay tres formas en las que pueden ser inválidas”.
Anti-patrón: Gherkin sin EARS de soporte
Si los escenarios Gherkin se escriben sin requisitos EARS previos, suelen quedar:
- Demasiado bajos (testean detalles de UI)
- Inconsistentes (cada autor inventa su forma)
- Difíciles de revisar por stakeholders (no hay nivel de abstracción adecuado)
Con EARS de soporte, los Gherkin se escriben como instanciación del requisito.
Anti-patrón: EARS sin Gherkin de verificación
Si los EARS no se traducen a tests automatizados, el contrato se rompe con el tiempo. EARS sin verificación es papel.
Flujo recomendado
flowchart TD
A[Stakeholder o PO<br/>describe necesidad] --> B[Requisitos en EARS]
B --> C[Refinamiento: discutir AC]
C --> D[Escenarios Gherkin<br/>derivados de cada REQ]
D --> E[Step definitions<br/>en código]
E --> F[Ejecutar BDD<br/>en CI]
F -->|todos pasan| G[Feature aceptada]
F -->|falla| H[Volver a REQ o impl]
Ejemplo completo: feature con trazabilidad
Spec EARS:
# Spec: Carrito de compras
REQ-CART-001: When the user adds a product to the cart, the cart service shall increment the quantity if the product is already in the cart, or insert it with quantity 1 if not.
REQ-CART-002: When the user removes a product from the cart, the cart service shall remove the line item completely regardless of quantity.
REQ-CART-003: While the cart is empty, the checkout button shall be disabled.
REQ-CART-004: If the cart subtotal exceeds $10000, then the cart service shall require manager approval before checkout.
Gherkin derivado:
Feature: Carrito de compras
@REQ-CART-001
Scenario: Agregar producto nuevo al carrito
Given un carrito vacío
When agrego el producto "P-100" al carrito
Then el carrito contiene 1 línea
And la línea de "P-100" tiene quantity 1
@REQ-CART-001
Scenario: Agregar producto que ya está en el carrito incrementa quantity
Given un carrito con la línea (P-100, quantity 2)
When agrego el producto "P-100" al carrito
Then el carrito contiene 1 línea
And la línea de "P-100" tiene quantity 3
@REQ-CART-002
Scenario: Remover producto elimina la línea completa
Given un carrito con la línea (P-100, quantity 5)
When remuevo el producto "P-100" del carrito
Then el carrito está vacío
@REQ-CART-003
Scenario: Botón checkout deshabilitado con carrito vacío
Given un carrito vacío
When abro la vista del carrito
Then el botón "Checkout" está deshabilitado
@REQ-CART-004
Scenario: Carrito sobre el límite requiere aprobación
Given un carrito con subtotal $15000
When inicio el checkout
Then la respuesta indica "requires_manager_approval: true"
And no se procesa el pago hasta recibir aprobación
Cada escenario traza a un REQ vía tag. Revisión y reportes triviales.
Resumen
- EARS define el qué (contrato del sistema)
- Gherkin define ejemplos verificables (cómo se prueba)
- 1 REQ → N escenarios típicamente
- Usá tags
@REQ-XXX-NNNpara trazabilidad - Los Scenario Outline son ideales para requisitos con
Where
En el siguiente capítulo encontrás plantillas y checklists listos para usar.