Living documentation y reportes

Por: Artiko
gherkinliving-documentationreportesallure

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”

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:

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

Allure features útiles

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:

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

En el siguiente capítulo volvemos sobre la integración Gherkin + EARS desde la perspectiva de Gherkin.