Refactorizar y mejorar suite de tests con validaciones robustas

Problemas resueltos:
- Eliminada dependencia de UUIDs hardcodeados en tests
- Agregadas validaciones específicas de valores esperados
- Implementado cleanup automático de datos de test

Cambios principales:

Tests organizados por categoría (7 archivos nuevos):
- test_structure.sql: 8 tests de estructura de BD
- test_constraints.sql: 6 tests de validaciones
- test_triggers.sql: 3 tests de triggers automáticos
- test_queries.sql: 5 tests de queries típicas
- test_functions.sql: 3 tests de funciones auxiliares
- test_edge_cases.sql: 7 tests de casos límite
- test_indexes.sql: 6 tests de uso de índices

Mejoras implementadas:
- Cada test genera sus propios datos dinámicamente
- Tests usan bloques DO $$ con UUIDs generados
- Validaciones específicas con valores esperados
- Cleanup automático al finalizar cada test
- Tests de casos edge (arrays vacíos, NULL, límites)
- Verificación de uso de índices con EXPLAIN

test_all.sql actualizado:
- Ahora ejecuta todos los archivos organizados
- Total: ~38 tests independientes y robustos
- Progreso visual por categoría
- ASCII art y mejor presentación

Todos los tests verificados y funcionando correctamente
This commit is contained in:
2025-10-17 17:35:34 -06:00
parent f682c3db51
commit cc3cf0da81
8 changed files with 2487 additions and 477 deletions

View File

@@ -0,0 +1,454 @@
-- ============================================
-- rioCata - Tests de Constraints
-- ============================================
-- Tests que verifican la validación de constraints
-- de la base de datos sin depender de datos hardcodeados
-- ============================================
\echo '=========================================='
\echo 'Tests de Constraints'
\echo '=========================================='
\echo ''
-- ============================================
-- TEST: Constraint tazas_no_uniformes (solo valores 1-5)
-- ============================================
\echo '[CONSTRAINT 1] Validando tazas_no_uniformes (valores 1-5)...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_participante_id uuid := gen_random_uuid();
test_muestra_id uuid := gen_random_uuid();
BEGIN
-- Crear datos de prueba
INSERT INTO auth.users (id, email, nombre)
VALUES (test_user_id, 'test_constraint1@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-CONST-1', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_participante_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M1');
-- Test 1: Valores válidos (1-5) deben pasar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades, tazas_no_uniformes
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
ARRAY[1,2,3,4,5]::smallint[]
);
RAISE NOTICE ' ✓ Acepta valores válidos 1-5';
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Rechazó valores válidos: %', SQLERRM;
END;
-- Test 2: Valor inválido (0) debe fallar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades, tazas_no_uniformes
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
ARRAY[0]::smallint[]
);
RAISE EXCEPTION ' ✗ Aceptó valor inválido 0';
EXCEPTION WHEN check_violation THEN
RAISE NOTICE ' ✓ Rechaza correctamente valor 0';
END;
-- Test 3: Valor inválido (6) debe fallar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades, tazas_no_uniformes
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
ARRAY[6]::smallint[]
);
RAISE EXCEPTION ' ✗ Aceptó valor inválido 6';
EXCEPTION WHEN check_violation THEN
RAISE NOTICE ' ✓ Rechaza correctamente valor 6';
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Constraint tazas_no_uniformes funciona correctamente';
END $$;
\echo ''
-- ============================================
-- TEST: Constraint tazas_defectuosas (solo valores 1-5)
-- ============================================
\echo '[CONSTRAINT 2] Validando tazas_defectuosas (valores 1-5)...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_participante_id uuid := gen_random_uuid();
test_muestra_id uuid := gen_random_uuid();
BEGIN
-- Crear datos de prueba
INSERT INTO auth.users (id, email, nombre)
VALUES (test_user_id, 'test_constraint2@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-CONST-2', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_participante_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M2');
-- Test: Valor inválido (-1) debe fallar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades, tazas_defectuosas
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
ARRAY[-1]::smallint[]
);
RAISE EXCEPTION ' ✗ Aceptó valor inválido -1';
EXCEPTION WHEN check_violation THEN
RAISE NOTICE ' ✓ Rechaza correctamente valor -1';
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Constraint tazas_defectuosas funciona correctamente';
END $$;
\echo ''
-- ============================================
-- TEST: Constraint gustos_predominantes (máximo 2 elementos)
-- ============================================
\echo '[CONSTRAINT 3] Validando gustos_predominantes (máximo 2 elementos)...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_participante_id uuid := gen_random_uuid();
test_muestra_id uuid := gen_random_uuid();
BEGIN
-- Crear datos de prueba
INSERT INTO auth.users (id, email, nombre)
VALUES (test_user_id, 'test_constraint3@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-CONST-3', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_participante_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M3');
-- Test 1: 0 elementos debe pasar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades, gustos_predominantes
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
ARRAY[]::text[]
);
RAISE NOTICE ' ✓ Acepta 0 elementos';
DELETE FROM evaluacion WHERE muestra_id = test_muestra_id;
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Rechazó 0 elementos: %', SQLERRM;
END;
-- Test 2: 1 elemento debe pasar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades, gustos_predominantes
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
ARRAY['Dulce']::text[]
);
RAISE NOTICE ' ✓ Acepta 1 elemento';
DELETE FROM evaluacion WHERE muestra_id = test_muestra_id;
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Rechazó 1 elemento: %', SQLERRM;
END;
-- Test 3: 2 elementos debe pasar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades, gustos_predominantes
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
ARRAY['Dulce', 'Ácido']::text[]
);
RAISE NOTICE ' ✓ Acepta 2 elementos';
DELETE FROM evaluacion WHERE muestra_id = test_muestra_id;
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Rechazó 2 elementos: %', SQLERRM;
END;
-- Test 4: 3 elementos debe fallar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades, gustos_predominantes
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
ARRAY['Dulce', 'Ácido', 'Amargo']::text[]
);
RAISE EXCEPTION ' ✗ Aceptó 3 elementos';
EXCEPTION WHEN check_violation THEN
RAISE NOTICE ' ✓ Rechaza correctamente 3 elementos';
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Constraint gustos_predominantes funciona correctamente';
END $$;
\echo ''
-- ============================================
-- TEST: Constraint sensacion_en_boca (valores permitidos)
-- ============================================
\echo '[CONSTRAINT 4] Validando sensacion_en_boca (valores permitidos)...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_participante_id uuid := gen_random_uuid();
test_muestra_id uuid := gen_random_uuid();
BEGIN
-- Crear datos de prueba
INSERT INTO auth.users (id, email, nombre)
VALUES (test_user_id, 'test_constraint4@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-CONST-4', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_participante_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M4');
-- Test 1: Valores válidos deben pasar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades, sensacion_en_boca
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
ARRAY['Áspero', 'Suave', 'Aceitoso', 'Metálico', 'Astringente']::text[]
);
RAISE NOTICE ' ✓ Acepta todos los valores permitidos';
DELETE FROM evaluacion WHERE muestra_id = test_muestra_id;
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Rechazó valores válidos: %', SQLERRM;
END;
-- Test 2: Valor inválido debe fallar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades, sensacion_en_boca
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
ARRAY['Raro', 'Extraño']::text[]
);
RAISE EXCEPTION ' ✗ Aceptó valores inválidos';
EXCEPTION WHEN check_violation THEN
RAISE NOTICE ' ✓ Rechaza correctamente valores inválidos';
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Constraint sensacion_en_boca funciona correctamente';
END $$;
\echo ''
-- ============================================
-- TEST: Constraint rangos de intensidades
-- ============================================
\echo '[CONSTRAINT 5] Validando rangos intensidades (descriptiva 1-15, afectiva 1-10)...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_participante_id uuid := gen_random_uuid();
test_muestra_id uuid := gen_random_uuid();
BEGIN
-- Crear datos de prueba
INSERT INTO auth.users (id, email, nombre)
VALUES (test_user_id, 'test_constraint5@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-CONST-5', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_participante_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M5');
-- Test 1: Valores en límites válidos (1 y 15 para descriptiva)
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":1,"afectiva":1},"aroma":{"descriptiva":15,"afectiva":10}}'::jsonb
);
RAISE NOTICE ' ✓ Acepta límites válidos (descriptiva: 1 y 15, afectiva: 1 y 10)';
DELETE FROM evaluacion WHERE muestra_id = test_muestra_id;
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Rechazó límites válidos: %', SQLERRM;
END;
-- Test 2: descriptiva < 1 debe fallar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":0,"afectiva":5}}'::jsonb
);
RAISE EXCEPTION ' ✗ Aceptó descriptiva=0';
EXCEPTION WHEN check_violation THEN
RAISE NOTICE ' ✓ Rechaza correctamente descriptiva < 1';
END;
-- Test 3: descriptiva > 15 debe fallar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":16,"afectiva":5}}'::jsonb
);
RAISE EXCEPTION ' ✗ Aceptó descriptiva=16';
EXCEPTION WHEN check_violation THEN
RAISE NOTICE ' ✓ Rechaza correctamente descriptiva > 15';
END;
-- Test 4: afectiva < 1 debe fallar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":0}}'::jsonb
);
RAISE EXCEPTION ' ✗ Aceptó afectiva=0';
EXCEPTION WHEN check_violation THEN
RAISE NOTICE ' ✓ Rechaza correctamente afectiva < 1';
END;
-- Test 5: afectiva > 10 debe fallar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":11}}'::jsonb
);
RAISE EXCEPTION ' ✗ Aceptó afectiva=11';
EXCEPTION WHEN check_violation THEN
RAISE NOTICE ' ✓ Rechaza correctamente afectiva > 10';
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Constraint rangos de intensidades funciona correctamente';
END $$;
\echo ''
-- ============================================
-- TEST: Constraint UNIQUE (una evaluación por participante/muestra)
-- ============================================
\echo '[CONSTRAINT 6] Validando constraint UNIQUE (una evaluación por participante/muestra)...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_participante_id uuid := gen_random_uuid();
test_muestra_id uuid := gen_random_uuid();
BEGIN
-- Crear datos de prueba
INSERT INTO auth.users (id, email, nombre)
VALUES (test_user_id, 'test_constraint6@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-CONST-6', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_participante_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M6');
-- Test 1: Primera evaluación debe pasar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb
);
RAISE NOTICE ' ✓ Acepta primera evaluación';
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Rechazó primera evaluación: %', SQLERRM;
END;
-- Test 2: Segunda evaluación de mismo participante/muestra debe fallar
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades
) VALUES (
test_muestra_id, test_participante_id,
'{"fragancia":{"descriptiva":7,"afectiva":8}}'::jsonb
);
RAISE EXCEPTION ' ✗ Permitió evaluación duplicada';
EXCEPTION WHEN unique_violation THEN
RAISE NOTICE ' ✓ Rechaza correctamente evaluación duplicada';
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Constraint UNIQUE funciona correctamente';
END $$;
\echo ''
\echo '=========================================='
\echo 'Tests de Constraints completados'
\echo '=========================================='