🧪 ESTÁNDAR AVANZADO DE PRUEBAS Y QA
🎯 OBJETIVO
Definir las técnicas de validación avanzadas para garantizar el rendimiento bajo presión, la resiliencia ante fallos catastróficos, la calidad visual y la cobertura efectiva de las aplicaciones.
🎯 REGLAS INQUEBRANTABLES
[REQUIRED] TEST-001: Pruebas de Carga (k6) OBLIGATORIAS antes de cada release mayor. Ninguna aplicación sale a producción sin validar que soporta el percentil 95 (P95) < 300ms al 150% de la carga esperada.
Por qué: una API que responde bien con un usuario de prueba puede colapsar con la carga real del día del lanzamiento, y ese es precisamente el peor momento para descubrirlo. Validar el percentil 95 bajo carga antes de una release mayor convierte una sorpresa en producción en un hallazgo en staging.
[REQUIRED] TEST-002: La cobertura de código (Coverage) mínima es del 80%. Los módulos de pagos, autenticación y seguridad exigen 95% de cobertura comprobada.
Por qué: un umbral global de cobertura no distingue entre una función trivial y el flujo de cobro; exigir más en pagos, autenticación y seguridad reconoce que el coste de un bug ahí no es comparable al de un bug en una utilidad de formato.
[RECOMMENDED] TEST-003: Pruebas de Mutación con Stryker > 70% Score. Las pruebas no solo se miden por las líneas ejecutadas, sino por su capacidad real de detectar fallos inducidos.
Por qué: la cobertura de líneas mide qué código se ejecutó, no si el test detectaría un bug real ahí — un test sin ninguna aserción puede dar 100% de cobertura sin comprobar nada. Mutation testing inyecta bugs sintéticos y mide si los tests los atrapan, que es la pregunta que de verdad importa. Es recomendado por su coste de ejecución: se reserva para los módulos críticos que ya exige
TEST-002, no para la base de código entera.
⚡ 1. PRUEBAS DE CARGA Y ESTRÉS CON K6
Script de Rendimiento k6
// tests/load/k6-load-test.js
import http from 'k6/http'
import { check, sleep } from 'k6'
export const options = {
stages: [
{ duration: '30s', target: 50 }, // Ramp-up a 50 Virtual Users (VUs)
{ duration: '1m', target: 200 }, // Carga sostenida de 200 VUs
{ duration: '30s', target: 0 } // Ramp-down
],
thresholds: {
http_req_duration: ['p(95)<300'], // 95% de peticiones por debajo de 300ms
http_req_failed: ['rate<0.01'] // Menos del 1% de errores HTTP
}
}
export default function () {
const res = http.get('https://api.collabscribe.com/api/public/documents/sample-token')
check(res, {
'status es 200': (r) => r.status === 200,
'tiempo < 250ms': (r) => r.timings.duration < 250
})
sleep(1)
}🎲 2. PROPERTY-BASED TESTING CON FAST-CHECK
Prueba funciones con cientos de inputs generados aleatoriamente para descubrir edge cases que ningún desarrollador imaginó.
// tests/unit/sanitize.test.ts
import { test, expect } from 'vitest'
import fc from 'fast-check'
import { sanitizeInput } from '@/lib/sanitize'
test('Property: sanitizeInput NUNCA debe retornar etiquetas script', () => {
fc.assert(
fc.property(fc.string(), (randomString) => {
const sanitized = sanitizeInput(randomString)
expect(sanitized).not.toContain('<script>')
expect(sanitized).not.toContain('</script>')
})
)
})🎨 3. VISUAL REGRESSION TESTING CON CHROMATIC / PERCY
Detecta cambios involuntarios de estilo o pixel-shift en componentes React.
// src/components/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react'
import { Button } from './Button'
const meta: Meta<typeof Button> = {
title: 'UI/Button',
component: Button
}
export default meta
export const Primary: StoryObj<typeof Button> = {
args: { variant: 'primary', children: 'Guardar Cambios' }
}
export const Danger: StoryObj<typeof Button> = {
args: { variant: 'danger', children: 'Eliminar Cuenta' }
}🤝 4. CONTRACT TESTING CON PACT
Garantiza que los cambios en el backend Worker no rompan el contrato consumido por el frontend React.
// tests/contract/consumer.spec.ts
import { PactV3, MatchersV3 } from '@pact-foundation/pact'
const provider = new PactV3({
consumer: 'ReactFrontend',
provider: 'DocsWorker'
})
test('Contrato API: Obtener documento por ID', async () => {
provider
.given('Existe el documento 123')
.uponReceiving('Petición de detalle de documento')
.withRequest({
method: 'GET',
path: '/api/documents/123'
})
.willRespondWith({
status: 200,
body: {
success: true,
data: {
id: MatchersV3.string('123'),
title: MatchersV3.string('Título de prueba')
}
}
})
await provider.executeTest(async (mockServer) => {
const res = await fetch(`${mockServer.url}/api/documents/123`)
const json = await res.json()
expect(json.data.title).toBe('Título de prueba')
})
})🧬 5. MUTATION TESTING CON STRYKER
Inyecta mutaciones (bugs sintéticos) en tu código para comprobar si tus pruebas fallan como deberían.
// stryker.config.json
{
"$schema": "./node_modules/@stryker-mutator/core/schema/stryker-schema.json",
"packageManager": "pnpm",
"reporters": ["html", "clear-text", "progress"],
"testRunner": "vitest",
"coverageAnalysis": "perTest",
"thresholds": { "high": 80, "low": 60, "break": 70 }
}📋 CHECKLIST AVANZADO DE QA
- [ ] Pruebas de carga k6 ejecutadas en entorno Staging.
- [ ] Percentil P95 < 300ms y tasa de error < 1% bajo 200 VUs.
- [ ] Cobertura de código en Vitest >= 80% global.
- [ ] Score de mutación en Stryker >= 70%.
- [ ] Capturas de regresión visual verificadas en Chromatic/Percy.