← Volver al portal de guías
🗄️ GUÍA DATABASE & DATA QUALITY TESTING
Schema · Integridad · Transacciones · Test Data Management · DQFI — Shift-left de datos alineado a ISO/IEC 25012 y DAMA-DMBOK
QA Shift-Left Methodology · by E-Gregorio
ISO/IEC 25012:2008 ISO/IEC 25010:2023 DAMA-DMBOK v2 ISO 31000:2018 OWASP Top 10 A02/A03 GDPR Art. 25 — Privacy by Design
Esta guía cubre cómo integrar el testing de la capa de datos en cada fase del ciclo Shift-Left: desde el contrato de datos como artefacto de DoR hasta las assertions de integridad post-E2E y el índice forense DQFI. La premisa: un defecto de datos encontrado en Fase 2 cuesta $1; encontrado en producción puede costar un breach regulatorio.
📋 Contenido

1. Shift-left de datos: el problema real

En proyectos reales, el equipo QA enfrenta tres escenarios recurrentes con los datos de prueba:

Escenario Situación Riesgo Solución Shift-Left
Sin datos Dev no provee datos. QA genera sintéticos ad-hoc. No se detectan problemas de calidad de datos reales. Golden Dataset versionado + Data Contract en DoR.
DB sin control Se da acceso a una BD de test controlada por dev. Puede cambiar sin aviso. Tests inestables. La culpa "cae" sobre QA cuando rompe. BD propia de QA. Schema validado contra contrato. Seed reproducible.
Datos reales Cliente autoriza uso de datos de producción para pruebas. Violación GDPR/LGPD si no hay anonimización. Riesgo legal. DPA firmado + pipeline de anonimización (Privacy by Design — GDPR Art. 25).

📋 Fase 1

  • Data Contract
  • DPA si datos reales
  • Definir PII

🔍 Fase 2

  • Schema review
  • DDL assertions
  • Constraints check

🚀 Fase 3

  • Golden Dataset seed
  • BD propia QA
  • Health check BD

🎯 Fase 4

  • VCR por assertions DB
  • ¿Automatizar?
  • Prioridad riesgo dato

⚡ Fase 5

  • DB assertions post-E2E
  • ACID tests
  • PII checks

📊 Fase 6

  • DQFI score
  • Grafana dashboard
  • Dictamen forense
📌 Regla de oro: QA debe ser dueño de sus datos de prueba igual que es dueño de sus test cases. Sin datos bajo control de QA, los tests son dependientes de terceros y su resultado no es reproducible.

2. Data Contract — DoR del dato

El Data Contract es el artefacto formal que define qué datos existen, cómo se estructuran y qué reglas deben cumplir. Es el DoR de la capa de datos: sin él, no se puede ejecutar ninguna prueba de datos válida.

¿Qué contiene un Data Contract?

Elemento Descripción Ejemplo
Entidades y tablas Listado de tablas/colecciones relevantes para la HU. users, orders, payments, audit_log
Tipos y formatos Tipo de dato esperado por columna. email: VARCHAR(255), NOT NULL, UNIQUE
Constraints de negocio Reglas que el dato debe cumplir más allá del DDL. password_hash NUNCA en texto plano · age >= 18
Campos PII Identificación de datos personales (GDPR/LGPD). email, full_name, phone, ip_address
Relaciones FK y relaciones entre entidades. orders.user_id → users.id (FK obligatoria)
Estados válidos Enumeración de valores permitidos. status IN ('pending','active','cancelled')
Volumen de referencia Orden de magnitud de registros en producción. users: ~50.000 · orders: ~250.000
⚠️ DoR bloqueante: Si el Data Contract no está firmado por el Analista Funcional y el Tech Lead, la Fase 2 (Schema Testing) no arranca. Este es un gate real del framework, no una recomendación opcional.

Plantilla mínima de Data Contract

DATA CONTRACT — [Nombre del Proyecto] Versión: 1.0 · Fecha: [YYYY-MM-DD] HU asociada: [HU_XXX] Firmado por: [Analista Funcional] · [Tech Lead] · [QA Lead] TABLA: users ───────────────────────────────────────────────── | Columna | Tipo | Constraint | PII | Regla de negocio | | id | BIGINT | PK, AUTO_INCREMENT | No | Generado por BD | | email | VARCHAR(255) | NOT NULL, UNIQUE | Sí | Formato RFC 5322 | | password_hash | VARCHAR(255) | NOT NULL | No | NUNCA texto plano (bcrypt) | | created_at | TIMESTAMP | NOT NULL, DEFAULT | No | UTC | | status | VARCHAR(20) | NOT NULL | No | IN('active','inactive') | RELACIONES: orders.user_id → users.id (FK, ON DELETE RESTRICT) CAMPOS PII IDENTIFICADOS: email POLÍTICA DE ENMASCARAMIENTO: email → anonimizar en ambiente QA

3. Schema Testing (Fase 2 — Pruebas Estáticas)

El schema es la primera línea de defensa de la calidad del dato. Un campo sin constraint a nivel BD es un defecto que la aplicación puede ocultar temporalmente pero que eventualmente produce datos corruptos.

Checklist de Schema Review

Check Qué verificar Comando SQL de validación Estado
PK definida Toda tabla tiene PRIMARY KEY explícita. SELECT table_name FROM information_schema.tables WHERE table_name NOT IN (SELECT table_name FROM information_schema.table_constraints WHERE constraint_type='PRIMARY KEY') ☐ OK / ☐ Defecto
FK con índice Toda FK tiene índice en la columna referenciada. SHOW INDEX FROM tabla ☐ OK / ☐ Defecto
NOT NULL críticos Columnas del Data Contract marcadas como NOT NULL lo son en DDL. SELECT column_name, is_nullable FROM information_schema.columns WHERE table_name='users' ☐ OK / ☐ Defecto
UNIQUE constraints Campos identificados como únicos tienen constraint UNIQUE. SELECT constraint_name FROM information_schema.table_constraints WHERE constraint_type='UNIQUE' ☐ OK / ☐ Defecto
Longitudes de VARCHAR Longitudes del DDL coinciden con el Data Contract. SELECT column_name, character_maximum_length FROM information_schema.columns WHERE table_name='users' ☐ OK / ☐ Defecto
ENUM/CHECK constraints Estados y enumeraciones tienen CHECK constraint o tipo ENUM. SELECT check_clause FROM information_schema.check_constraints ☐ OK / ☐ Defecto
Sin columnas huérfanas No existen columnas en BD que no estén en el Data Contract. Comparar information_schema.columns contra el contrato. ☐ OK / ☐ Defecto
✅ Shift-Left en acción: Un schema sin FK en una relación crítica es un defecto de Severidad 2. Detectarlo en Fase 2 (antes del primer commit de dev) elimina el riesgo de datos huérfanos en producción.

Ejemplo de assertion de schema (Python + psycopg2)

# schema_assertions.py — ejecutar en Fase 2 contra BD de QA import psycopg2 def assert_schema(conn): cur = conn.cursor() # 1. Verificar que email sea NOT NULL y UNIQUE cur.execute(""" SELECT is_nullable, column_default FROM information_schema.columns WHERE table_name='users' AND column_name='email' """) row = cur.fetchone() assert row[0] == 'NO', "DEFECTO: email permite NULL" # 2. Verificar FK orders → users cur.execute(""" SELECT COUNT(*) FROM information_schema.referential_constraints WHERE constraint_name = 'fk_orders_user_id' """) assert cur.fetchone()[0] == 1, "DEFECTO: FK orders.user_id no definida" # 3. Verificar que password_hash no almacene texto plano cur.execute("SELECT COUNT(*) FROM users WHERE LENGTH(password_hash) < 60") assert cur.fetchone()[0] == 0, "DEFECTO: passwords sin hashear detectados" print("✅ Schema assertions: PASSED")

4. Test Data Management — Golden Dataset y Enmascaramiento

Estrategia A: Golden Dataset (sin datos reales)

El Golden Dataset es un conjunto de datos sintéticos, versionado en Git, que siembra la BD de QA antes de cada ejecución del pipeline. QA lo controla 100%.

Principio Descripción
Representatividad Los datos cubren todos los escenarios del Data Contract: valores límite, formatos extremos, estados válidos e inválidos.
Reproducibilidad El mismo seed produce exactamente los mismos datos. El pipeline es determinista.
Versionado El seed script vive en Git junto al código. Cambia con el Data Contract.
Aislamiento Cada ejecución del pipeline restaura la BD desde el seed. Los tests no se contaminan entre sí.
-- seed.sql — Golden Dataset para HU_REG_01 TRUNCATE users RESTART IDENTITY CASCADE; INSERT INTO users (email, password_hash, status) VALUES ('user.activo@qasl.test', '$2b$12$...', 'active'), -- TC positivo ('user.inactivo@qasl.test', '$2b$12$...', 'inactive'), -- TC negativo estado ('unicode.ñoño@qasl.test', '$2b$12$...', 'active'), -- TC unicode ('max255chars@' || repeat('a',240) || '.test', '$2b$12$...', 'active'); -- límite

Estrategia B: Datos reales enmascarados (con autorización)

🔴 OBLIGATORIO antes de usar datos reales:
  1. DPA firmado (Data Processing Agreement) — contrato legal con el cliente que especifica: qué datos, qué enmascaramiento, en qué ambiente, con qué retención.
  2. Anonimización verificada — no solo pseudonimización. El dato enmascarado no debe poder re-identificarse.
  3. Auditoría del proceso — el pipeline de anonimización debe ser trazable y reproducible.
Base normativa: GDPR Art. 25 (Privacy by Design) · ISO/IEC 27001:2022 · ISO/IEC 25012
Técnica de enmascaramiento Aplica a Ejemplo
Sustitución Nombres, emails, teléfonos juan.perez@empresa.com → user_4829@qasl.test
Shuffling Datos numéricos, fechas Redistribuir valores del mismo campo entre filas
Nulling Campos no necesarios para el test phone_number → NULL
Tokenización Números de tarjeta, DNI 4111111111111111 → TOK_a83f9e2c
Perturbación Montos, edades, coordenadas Añadir ruido gaussiano ±5%

5. Data Integrity Testing — Assertions post-E2E

Después de que Playwright ejecuta un flujo E2E completo, las DB assertions verifican que el estado de la base de datos sea exactamente el esperado. Lo que el UI muestra puede diferir de lo que realmente quedó persistido.

Tipos de assertions de integridad

Tipo Qué valida Ejemplo de query Caso de prueba
Existencia El registro fue creado (o eliminado). SELECT COUNT(*) FROM users WHERE email='nuevo@test.com' TC-001: Registro exitoso → usuario existe en BD
Valores Los campos tienen los valores esperados post-operación. SELECT status FROM users WHERE email='...' TC-002: Estado correcto post-registro
No-existencia Registros inválidos NO fueron creados. SELECT COUNT(*) FROM users WHERE email='inválido' TC-003: Registro fallido → NO existe en BD (BUG-001 type)
Integridad referencial FK correctamente vinculadas post-operación. SELECT o.id FROM orders o LEFT JOIN users u ON o.user_id=u.id WHERE u.id IS NULL TC-004: Sin órdenes huérfanas
Seguridad del dato PII no almacenada en texto plano. SELECT COUNT(*) FROM users WHERE LENGTH(password_hash) < 60 TC-005: Password hasheado — alinea a OWASP A02
Auditoría Registro de auditoría creado para operaciones críticas. SELECT COUNT(*) FROM audit_log WHERE entity='user' AND action='CREATE' TC-006: Log de creación de usuario existe
✅ Conexión con BUG-001 de QASL Framework: TC-008/009/015 del framework detectaron que el SUT aceptaba passwords de 5 y 1 caracteres. Una assertion de BD post-registro habría confirmado que el dato corrupto quedó persistido — dando evidencia doble: UI + BD, severidad reforzada.

6. Transaction Testing — ACID

Las propiedades ACID (Atomicity, Consistency, Isolation, Durability) son los contratos que la BD hace con la aplicación. Cuando se violan, los datos quedan en estados inconsistentes que ningún test de UI detecta.

Propiedad Qué significa Cómo testearla Escenario de falla
Atomicity La transacción completa o no hace nada. Simular falla en el paso N de una transacción multi-step. Verificar rollback completo. Pago registrado en tabla payments pero orden sin actualizar en orders.
Consistency La BD pasa de un estado válido a otro válido. Verificar constraints post-transacción. Ninguna constraint debe violarse. Balance de cuenta negativo tras débito sin validación.
Isolation Transacciones concurrentes no interfieren entre sí. Ejecutar 2+ transacciones en paralelo (K6 con 2 VUs) sobre el mismo recurso. Dos usuarios registran el mismo email simultáneamente. Uno debería fallar.
Durability Los datos confirmados persisten ante fallos. Verificar que datos existen en BD después de reiniciar el servicio. Registro exitoso en UI pero dato perdido después de reinicio del servidor.

Ejemplo: Test de Isolation con K6

// isolation_test.k6.js — 2 VUs registrando el mismo email concurrentemente import http from 'k6/http'; import { check } from 'k6'; export const options = { vus: 2, iterations: 2 }; export default function() { const payload = JSON.stringify({ email: 'duplicate@qasl.test', // mismo email en ambos VUs password: 'ValidPass123' }); const res = http.post('http://localhost:3000/api/register', payload, { headers: { 'Content-Type': 'application/json' } }); // Exactamente 1 debe ser 201 y 1 debe ser 409 (conflict) check(res, { 'respuesta válida (201 o 409)': (r) => [201, 409].includes(r.status), }); // Post-test: SELECT COUNT(*) FROM users WHERE email='duplicate@qasl.test' debe = 1 }

7. Query Performance Testing

Una query lenta en producción es un defecto de calidad del dato igual que un valor nulo inesperado. Se detecta antes del release, no cuando el DBA recibe la alerta a las 3 AM.

Check Herramienta Umbral de alerta Acción
Full table scan EXPLAIN ANALYZE type = ALL en queries frecuentes Agregar índice en la columna filtrada.
Query time p95 K6 + slow query log > 500 ms en operaciones CRUD básicas Revisar índices, N+1, joins innecesarios.
N+1 queries Query log / ORM profiler Más de 1 query por entidad en listados Usar JOINs o eager loading.
Lock contention pg_locks / SHOW STATUS Waits > 100ms bajo 2 VUs Revisar isolation level y orden de locks.
-- Verificar que la query de login usa índice (no full scan) EXPLAIN ANALYZE SELECT id, status FROM users WHERE email = 'user@test.com'; -- Resultado esperado: Index Scan using users_email_idx (NO Seq Scan) -- Si aparece "Seq Scan" → DEFECTO: falta índice en users.email

8. Data Security Testing

La capa de BD es el objetivo final de los ataques de inyección y la última línea de defensa para los datos sensibles. Alineado a OWASP Top 10 A02 (Cryptographic Failures) y A03 (Injection).

Riesgo OWASP Check en capa BD Query de validación
A02 · Cryptographic Failures Passwords nunca en texto plano. Datos sensibles encriptados. SELECT COUNT(*) FROM users WHERE LENGTH(password_hash) < 60 OR password_hash NOT LIKE '$2%'
A02 · PII en logs Logs de BD no contienen PII (email, nombre, DNI). Revisar slow query log / general log por patrones de email.
A03 · SQL Injection Inputs del usuario parametrizados antes de llegar a BD. Intentar '; DROP TABLE users; -- vía API. Verificar que BD no ejecuta el DROP.
Excessive data exposure Endpoints no devuelven columnas que no deben (password_hash, etc.). Interceptar respuesta API. Verificar que password_hash no aparece en ningún response.
Permisos de BD Usuario de la app tiene mínimos privilegios (no DROP, no GRANT). SHOW GRANTS FOR 'app_user'@'%'

9. Pipeline de Database Testing integrado

El DB testing no es un paso separado — se integra al pipeline existente del QASL Framework como una capa adicional que se ejecuta en paralelo o post-E2E.

🔍 Pre-pipeline

  • Schema assertions
  • Seed Golden Dataset
  • DB health check

🎭 E2E (Playwright)

  • Flujos funcionales
  • HAR capture
  • Screenshots

🗄️ DB Assertions

  • Post-E2E integrity
  • ACID checks
  • PII validation

⚡ API (Newman)

  • Contract testing
  • HAR replay

🏎️ Performance (K6)

  • Load + isolation
  • Query p95

📊 DQFI + Grafana

  • Score D1/D2/D3
  • Dashboard

GitHub Actions — stage de DB Testing

# .github/workflows/qa-pipeline.yml — stage de DB assertions db-assertions: name: 'F10.1.5 · DB Assertions post-E2E' needs: [e2e-tests] runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Python uses: actions/setup-python@v5 with: { python-version: '3.11' } - name: Install dependencies run: pip install psycopg2-binary pytest - name: Seed Golden Dataset run: psql $DB_URL -f seed/golden_dataset.sql - name: Run schema assertions run: pytest tests/db/schema_assertions.py -v - name: Run integrity assertions run: pytest tests/db/integrity_assertions.py -v - name: Run security assertions run: pytest tests/db/security_assertions.py -v - name: Generate DQFI score run: python scripts/calculate_dqfi.py --output reports/db/dqfi.json

10. DQFI — Data Quality Forensic Index

El DQFI (Data Quality Forensic Index) es el índice forense de la capa de datos. Convierte los resultados de las assertions en un score 0–100 con grado A→F, siguiendo el mismo patrón que CFQI (AppSec) y AFQI (AI/LLM) del ecosistema QASL.

📌 Base normativa: ISO/IEC 25012:2008 define las 15 características de calidad del dato (Accuracy, Completeness, Consistency, Currentness, Accessibility, Compliance, Confidentiality, Efficiency, Precision, Traceability, Understandability, Availability, Portability, Recoverability). El DQFI opera sobre las 5 más críticas en contexto de QA.

Las tres dimensiones del DQFI

D1 · Integridad Estructural — 35%

Calidad del schema y las constraints. Mide la salud de la BD en reposo.

  • PKs definidas en todas las tablas
  • FKs con índices correctos
  • NOT NULL en campos del Data Contract
  • Constraints de formato (VARCHAR lengths, ENUMs, CHECKs)

Herramientas: information_schema queries · sqlfluff · schemaspy

D2 · Calidad del Dato — 35%

Calidad del contenido persistido. Mide lo que está mal en los datos reales.

  • NULLs en campos NOT NULL (datos pre-existentes corruptos)
  • Formatos inválidos (emails malformados, fechas fuera de rango)
  • Violaciones de reglas de negocio (passwords sin hashear, estados inválidos)
  • Duplicados en campos UNIQUE
  • Integridad referencial (registros huérfanos)

Herramientas: Great Expectations · assertions SQL custom · dbt tests

D3 · Consistencia Transaccional — 30%

Comportamiento bajo operaciones concurrentes y adversas. Mide ACID bajo presión.

  • Atomicidad: rollback correcto en transacciones parciales
  • Isolation: sin race conditions bajo 2+ VUs concurrentes
  • Durabilidad: datos confirmados persisten ante reinicios
  • Query performance p95 bajo SLO definido

Herramientas: K6 + DB assertions · pg_locks · slow query log

Penalización Λ (Lambda)

🔴 Penalización crítica: Si se detecta PII almacenada en texto plano, o datos financieros sin encriptar, se aplica una penalización Λ que degrada el score a D automaticamente, independientemente de D1/D2/D3. Un proyecto no puede tener grado A con un breach de datos activo.

Tabla de grados DQFI

Score Grado Interpretación Acción recomendada
90–100 A Capa de datos en excelente estado. Release autorizado. Mantener. Monitorear en producción.
75–89 B Pequeñas deudas de calidad. No bloquea release. Documentar. Resolver en próximo sprint.
60–74 C Problemas de calidad de dato notables. Riesgo moderado. Resolver antes del release. Mínimo aceptable.
40–59 D Problemas serios de integridad o consistencia. Bloquear release hasta resolver críticos.
0–39 F Capa de datos no apta. Posible breach o corrupción activa. Detener pipeline. Investigar inmediatamente.

11. Métricas e indicadores

Métrica Fórmula / Fuente Umbral objetivo Dashboard
DQFI Score D1×0.35 + D2×0.35 + D3×0.30 − Λ ≥ 75 (grado B) Grafana · panel DQFI gauge
Schema Assertions Pass Rate Assertions OK / Total assertions × 100 100% (bloqueante) Grafana · panel D1
Integrity Assertions Pass Rate Assertions OK / Total assertions × 100 ≥ 95% Grafana · panel D2
Query p95 Percentil 95 de latencia de queries críticas < 500ms Grafana · panel D3
PII Exposure Rate Registros con PII en texto plano / Total 0% (bloqueante Λ) Grafana · panel seguridad
Seed Reproducibility Hash del estado de BD post-seed debe ser idéntico en cada run 100% idéntico CI log

12. Anti-patterns en Database Testing

Anti-pattern Por qué es peligroso Solución
Tests que comparten estado de BD Un test contamina los datos del siguiente. Resultados no reproducibles. Seed antes de cada ejecución. Transacciones con rollback en tests unitarios de BD.
Probar solo via UI El UI puede mostrar éxito mientras el dato quedó corrupto en BD. Siempre combinar: assertion UI + assertion BD para flujos críticos.
Usar BD de producción para tests Riesgo de borrado/corrupción de datos reales. Violación GDPR. BD propia de QA, aislada, controlada. Golden Dataset o datos enmascarados.
Ignorar el schema hasta que falla Un campo sin NOT NULL produce datos corruptos que tardan meses en detectarse. Schema assertions en Fase 2, antes del primer commit de dev.
Data Contract verbal "El equipo sabe cómo son los datos" — hasta que rotan personas o cambia el equipo. Data Contract escrito, versionado en Git, firmado como DoR.
No testear ACID bajo concurrencia Los bugs de isolation aparecen en producción bajo carga real, no en tests seriales. Usar K6 con 2+ VUs sobre los mismos recursos. Testear race conditions.

🔗 Integración con el QA Shift-Left Methodology

Esta guía es la extensión de capa de datos del framework. Se integra como sigue:

  • Data Contract → DoR de la Fase 1 (Análisis). Sin Data Contract firmado, no arranca Schema Testing.
  • Schema Testing → Fase 2 (Pruebas Estáticas). Mismo principio: validar antes del código.
  • Golden Dataset → Fase 3 (Deploy SUT). QA siembra su propia BD. Sin dependencia de Dev.
  • VCR para DB assertions → Fase 4 (Planning Poker). VCR ≥ 9 → automatizar assertions de BD.
  • DB Assertions post-E2E → Fase 5 (Ejecución). Capa adicional al pipeline E2E → API → K6 → ZAP.
  • DQFI en Grafana → Fase 6 (Métricas). Quinta capa del Quality Cockpit.
← Volver al portal de guías
QA Shift-Left Methodology · by E-Gregorio
Guía Database & Data Quality Testing · DQFI v1.0
ISO/IEC 25012:2008 · DAMA-DMBOK v2 · ISO 31000:2018 · OWASP Top 10 A02/A03 · GDPR Art. 25