Living documentation y reportes
Living documentation y reportes
Una de las grandes promesas de BDD es living documentation: los escenarios Gherkin son a la vez especificación, tests automatizados y documentación legible. Para que esta promesa se materialice, hay que invertir en reportes y publicación.
Por qué “living”
- Sincronizada con el código: si la spec se rompe, el test falla, el reporte lo señala
- Actualizada automáticamente: cada commit la regenera
- Auditable: stakeholders pueden leerla sin abrir el código
- Verificable: cada bullet es ejecutable
Esto la diferencia de la documentación tradicional (Confluence, Word, wikis) que se desactualiza el día que se publica.
Tipos de reportes en Cucumber-JS
Pretty (consola)
cucumber-js --format=@cucumber/pretty-formatter
Output legible en terminal — útil para desarrollo local.
Progress (consola)
cucumber-js --format=progress-bar
Una barra de progreso. Útil en CI.
JSON
cucumber-js --format=json:reports/cucumber.json
Output máquina-legible. Lo consumen Allure, Cucumber Studio, jenkins-cucumber-reports, etc.
HTML
cucumber-js --format=html:reports/cucumber.html
Un HTML autocontenido con todos los scenarios, pasos, evidencias adjuntadas. Lo abrís en el navegador.
Multi-formatter
cucumber-js \
--format=progress-bar \
--format=html:reports/cucumber.html \
--format=json:reports/cucumber.json
Útil en CI: progress en stdout, HTML para revisión humana, JSON para integraciones.
Reportes en behave
# Pretty (default)
behave --format=pretty
# JUnit XML (para CI)
behave --format=junit --junit-directory=reports
# JSON
behave --format=json --outfile=reports/behave.json
# Plain (para CI sin colores)
behave --format=plain
# Multiple
behave --format=pretty --format=junit --junit-directory=reports
Allure: el dashboard premium
Allure es una plataforma de reportes que va más allá de pass/fail. Soporta Cucumber y behave nativamente.
Cucumber-JS + Allure
npm install --save-dev allure-cucumberjs allure-commandline
// cucumber.cjs
const { AllureCucumber } = require('allure-cucumberjs')
module.exports = {
default: {
formatter: {
[AllureCucumber.name]: 'allure-cucumberjs'
},
format: ['progress-bar', 'allure-cucumberjs:reports/allure-results.json']
}
}
Generar el dashboard:
npx allure generate reports/allure-results -o reports/allure-report --clean
npx allure open reports/allure-report
Output:
- Dashboard con métricas (pass rate, duración, trends a través del tiempo)
- Filtros por severity, feature, tag, status
- Histórico (trends entre runs)
- Severity (blocker, critical, normal, minor, trivial)
- Adjuntos (screenshots, logs, JSON dumps)
behave + Allure
pip install allure-behave
behave -f allure_behave.formatter:AllureFormatter -o reports/allure-results
allure generate reports/allure-results -o reports/allure-report --clean
allure open reports/allure-report
Cucumber Reports (cloud, oficial)
reports.cucumber.io es el servicio oficial gratuito (con cuenta). Publicás reports desde CI:
cucumber-js --publish
Te devuelve una URL pública o privada con el reporte. Útil para PRs (linkeás el reporte de CI).
Configurá tu token:
export CUCUMBER_PUBLISH_TOKEN=tu-token
cucumber-js --publish
Publicar como documentación
Los reportes HTML pueden publicarse como sitio estático:
# .github/workflows/docs.yml
name: Living docs
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm ci
- run: npx cucumber-js --format=html:dist/index.html
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
Cada merge a main regenera y publica el reporte en GitHub Pages. La spec viva está en https://<owner>.github.io/<repo>/.
Anotar evidencias
Adjuntar evidencias en los reports es clave para debugging cuando algo falla.
Cucumber-JS
After(async function (scenario) {
if (scenario.result?.status === 'FAILED') {
if (this.page) {
const screenshot = await this.page.screenshot()
this.attach(screenshot, 'image/png')
}
if (this.response) {
this.attach(JSON.stringify(this.response, null, 2), 'application/json')
}
if (this.consoleLogs) {
this.attach(this.consoleLogs.join('\n'), 'text/plain')
}
}
})
behave + Allure
import allure
def after_step(context, step):
if step.status == 'failed':
if hasattr(context, 'browser'):
allure.attach(
context.browser.get_screenshot_as_png(),
name='screenshot',
attachment_type=allure.attachment_type.PNG
)
Métricas y dashboards
Métricas típicas
- Pass rate: porcentaje de scenarios que pasan
- Coverage por tag: cuántos
@smoke,@regression,@criticalpasan - Coverage por feature: cuántos scenarios pasan por feature
- Duración: tiempo total, p95, scenarios más lentos
- Trends: comparar entre runs y branches
- Flakiness: scenarios que pasan/fallan intermitentemente
Allure features útiles
- Categories: agrupar fallos por tipo (assertion, timeout, network)
- Severity: trivial / minor / normal / critical / blocker
- Environment: capturar info del entorno (versión, URL, browser)
- Behaviours: agrupar features por epic / capability
Trazabilidad: feature ↔ requisito
Usando tags @REQ-XXX-NNN (vimos en el capítulo de tags), los reportes pueden generar un mapa de cobertura:
REQ-AUTH-001 [3 scenarios — todos pasan]
REQ-AUTH-002 [2 scenarios — 1 falla] ⚠
REQ-AUTH-003 [0 scenarios — sin cobertura] ⚠
Script simple para generar este mapa desde cucumber.json:
import fs from 'fs'
const report = JSON.parse(fs.readFileSync('reports/cucumber.json', 'utf-8'))
const coverage = new Map<string, { total: number; passed: number; failed: number }>()
for (const feature of report) {
for (const scenario of feature.elements ?? []) {
const reqTags = (scenario.tags ?? [])
.map(t => t.name)
.filter(name => /^@REQ-/.test(name))
const status = scenario.steps.every(s => s.result?.status === 'passed') ? 'passed' : 'failed'
for (const tag of reqTags) {
const c = coverage.get(tag) ?? { total: 0, passed: 0, failed: 0 }
c.total++
if (status === 'passed') c.passed++
else c.failed++
coverage.set(tag, c)
}
}
}
for (const [req, c] of coverage) {
const status = c.failed === 0 ? '✓' : '✗'
console.log(`${status} ${req} — ${c.passed}/${c.total} scenarios passing`)
}
Publicar specs sin ejecutar tests
A veces querés mostrar los .feature como documentación antes de implementar las step definitions. Herramientas:
- Pickles: parsea
.featurey genera Markdown/HTML - gherkin-utils: SDK para procesar features programáticamente
- Manual con CommonMark: convertí cada
.featurea un bloque de código en una página Astro/Docusaurus/MkDocs
Anti-patrones de reportes
1. Reportes que nadie lee
- Generar HTML report, subirlo a S3, nadie lo abre
+ Publicar URL en el PR comment, en Slack #qa, en el dashboard del equipo
2. Reportes sin acceso para stakeholders
- Solo CI tiene los reportes; el PM nunca los ve
+ Publicar living docs en GitHub Pages o sitio público
3. Reportes sin evidencias
- "Test failed: AssertionError"
+ "Test failed: AssertionError" + screenshot + logs + JSON del response
4. Reportes históricos perdidos
- Cada run sobrescribe el report
+ Allure trends mantiene histórico; o S3 con timestamp por run
Resumen
- Reportes HTML/JSON/JUnit out-of-the-box
- Allure para dashboards avanzados
- Cucumber Reports servicio oficial gratuito
- Publicar como living docs en GitHub Pages
- Trazabilidad vía tags
@REQ-* - Adjuntar evidencias en falla
En el siguiente capítulo volvemos sobre la integración Gherkin + EARS desde la perspectiva de Gherkin.