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,432 @@
-- ============================================
-- rioCata - Tests de Casos Límite (Edge Cases)
-- ============================================
-- Tests que verifican comportamiento en casos límite
-- y situaciones especiales
-- ============================================
\echo '=========================================='
\echo 'Tests de Casos Límite'
\echo '=========================================='
\echo ''
-- ============================================
-- TEST: Arrays vacíos son válidos
-- ============================================
\echo '[EDGE 1] Validando arrays vacíos...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_part_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_edge1@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-EDGE-1', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_part_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M1');
-- Test: evaluación con todos los arrays vacíos
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades,
tazas_no_uniformes, tazas_defectuosas,
sensacion_en_boca, gustos_predominantes
) VALUES (
test_muestra_id, test_part_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
ARRAY[]::smallint[], ARRAY[]::smallint[],
ARRAY[]::text[], ARRAY[]::text[]
);
RAISE NOTICE ' ✓ Acepta arrays vacíos correctamente';
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Rechazó arrays vacíos: %', SQLERRM;
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Arrays vacíos funcionan correctamente';
END $$;
\echo ''
-- ============================================
-- TEST: Campos opcionales en NULL
-- ============================================
\echo '[EDGE 2] Validando campos opcionales en NULL...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_part_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_edge2@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-EDGE-2', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_part_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M2');
-- Test: evaluación con campos opcionales en NULL
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades,
defecto, otras_notas
) VALUES (
test_muestra_id, test_part_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
NULL, NULL
);
RAISE NOTICE ' ✓ Acepta campos opcionales NULL';
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Rechazó campos NULL: %', SQLERRM;
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Campos opcionales NULL funcionan correctamente';
END $$;
\echo ''
-- ============================================
-- TEST: JSONB con solo un parámetro
-- ============================================
\echo '[EDGE 3] Validando intensidades con un solo parámetro...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_part_id uuid := gen_random_uuid();
test_muestra_id uuid := gen_random_uuid();
puntaje int;
BEGIN
-- Crear datos de prueba
INSERT INTO auth.users (id, email, nombre)
VALUES (test_user_id, 'test_edge3@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-EDGE-3', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_part_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M3');
-- Test: solo un parámetro en intensidades
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades
) VALUES (
test_muestra_id, test_part_id,
'{"fragancia":{"descriptiva":5,"afectiva":7}}'::jsonb
) RETURNING puntaje_final INTO puntaje;
IF puntaje = 7 THEN
RAISE NOTICE ' ✓ Acepta un solo parámetro y calcula puntaje correcto: %', puntaje;
ELSE
RAISE EXCEPTION ' ✗ Puntaje incorrecto con un parámetro: % (esperado: 7)', puntaje;
END IF;
EXCEPTION WHEN check_violation THEN
RAISE EXCEPTION ' ✗ Rechazó un solo parámetro: %', SQLERRM;
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Un solo parámetro funciona correctamente';
END $$;
\echo ''
-- ============================================
-- TEST: Valores descriptivos NULL con afectivos presentes
-- ============================================
\echo '[EDGE 4] Validando descriptiva NULL con afectiva presente...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_part_id uuid := gen_random_uuid();
test_muestra_id uuid := gen_random_uuid();
puntaje int;
BEGIN
-- Crear datos de prueba
INSERT INTO auth.users (id, email, nombre)
VALUES (test_user_id, 'test_edge4@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-EDGE-4', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_part_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M4');
-- Test: impresionGlobal con descriptiva NULL (caso común)
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades
) VALUES (
test_muestra_id, test_part_id,
'{"impresionGlobal":{"descriptiva":null,"afectiva":8}}'::jsonb
) RETURNING puntaje_final INTO puntaje;
IF puntaje = 8 THEN
RAISE NOTICE ' ✓ Acepta descriptiva NULL y calcula puntaje correcto: %', puntaje;
ELSE
RAISE EXCEPTION ' ✗ Puntaje incorrecto: % (esperado: 8)', puntaje;
END IF;
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Rechazó descriptiva NULL: %', SQLERRM;
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Descriptiva NULL funciona correctamente';
END $$;
\echo ''
-- ============================================
-- TEST: JSONB arrays con múltiples elementos
-- ============================================
\echo '[EDGE 5] Validando arrays JSONB con múltiples notas...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_part_id uuid := gen_random_uuid();
test_muestra_id uuid := gen_random_uuid();
notas_count int;
BEGIN
-- Crear datos de prueba
INSERT INTO auth.users (id, email, nombre)
VALUES (test_user_id, 'test_edge5@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-EDGE-5', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_part_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M5');
-- Test: múltiples notas de fragancia/aroma
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades,
fragancia_aroma_notas, sabor_notas
) VALUES (
test_muestra_id, test_part_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
'[
{"categoria":"Afrutado","subcategoria":"Cítricos","notaEspecifica":"Naranja"},
{"categoria":"Floral","subcategoria":"Jazmín","notaEspecifica":null},
{"categoria":"Especiado","subcategoria":"Canela","notaEspecifica":"Canela dulce"}
]'::jsonb,
'[
{"categoria":"Chocolatado","subcategoria":"Chocolate negro","notaEspecifica":null},
{"categoria":"Nueces","subcategoria":"Almendra","notaEspecifica":"Tostada"}
]'::jsonb
);
-- Verificar que se guardaron correctamente
SELECT jsonb_array_length(fragancia_aroma_notas)
INTO notas_count
FROM evaluacion
WHERE muestra_id = test_muestra_id;
IF notas_count = 3 THEN
RAISE NOTICE ' ✓ Acepta múltiples notas de fragancia (3)';
ELSE
RAISE EXCEPTION ' ✗ Cantidad incorrecta de notas: % (esperado: 3)', notas_count;
END IF;
SELECT jsonb_array_length(sabor_notas)
INTO notas_count
FROM evaluacion
WHERE muestra_id = test_muestra_id;
IF notas_count = 2 THEN
RAISE NOTICE ' ✓ Acepta múltiples notas de sabor (2)';
ELSE
RAISE EXCEPTION ' ✗ Cantidad incorrecta de notas: % (esperado: 2)', notas_count;
END IF;
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Rechazó múltiples notas: %', SQLERRM;
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Arrays JSONB con múltiples elementos funcionan correctamente';
END $$;
\echo ''
-- ============================================
-- TEST: Evaluación mínima válida (solo intensidades requeridas)
-- ============================================
\echo '[EDGE 6] Validando evaluación mínima válida...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_part_id uuid := gen_random_uuid();
test_muestra_id uuid := gen_random_uuid();
eval_id uuid;
BEGIN
-- Crear datos de prueba
INSERT INTO auth.users (id, email, nombre)
VALUES (test_user_id, 'test_edge6@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-EDGE-6', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_part_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M6');
-- Test: solo intensidades (campo obligatorio), todo lo demás default/NULL
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades
) VALUES (
test_muestra_id, test_part_id,
'{"fragancia":{"descriptiva":1,"afectiva":1}}'::jsonb
) RETURNING id INTO eval_id;
-- Verificar que los defaults se aplicaron
PERFORM 1
FROM evaluacion
WHERE id = eval_id
AND fragancia_aroma_notas = '[]'::jsonb
AND sabor_notas = '[]'::jsonb
AND tazas_no_uniformes = ARRAY[]::smallint[]
AND tazas_defectuosas = ARRAY[]::smallint[]
AND sensacion_en_boca = ARRAY[]::text[]
AND gustos_predominantes = ARRAY[]::text[]
AND defecto IS NULL
AND otras_notas IS NULL;
IF FOUND THEN
RAISE NOTICE ' ✓ Evaluación mínima válida con defaults correctos';
ELSE
RAISE EXCEPTION ' ✗ Defaults no se aplicaron correctamente';
END IF;
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Rechazó evaluación mínima: %', SQLERRM;
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Evaluación mínima válida funciona correctamente';
END $$;
\echo ''
-- ============================================
-- TEST: Texto largo en otras_notas
-- ============================================
\echo '[EDGE 7] Validando texto largo en otras_notas...'
DO $$
DECLARE
test_sesion_id uuid := gen_random_uuid();
test_user_id uuid := gen_random_uuid();
test_part_id uuid := gen_random_uuid();
test_muestra_id uuid := gen_random_uuid();
long_text text;
stored_text text;
BEGIN
-- Crear datos de prueba
INSERT INTO auth.users (id, email, nombre)
VALUES (test_user_id, 'test_edge7@test.com', 'Test User');
INSERT INTO sesion (id, codigo, fecha)
VALUES (test_sesion_id, 'TEST-EDGE-7', CURRENT_DATE);
INSERT INTO sesion_participante (id, sesion_id, catador_id)
VALUES (test_part_id, test_sesion_id, test_user_id);
INSERT INTO muestra (id, sesion_id, codigo)
VALUES (test_muestra_id, test_sesion_id, 'TEST-M7');
-- Generar texto de 1000 caracteres
long_text := repeat('Este es un texto largo con muchos detalles sobre la catación. ', 20);
-- Test: insertar texto largo
BEGIN
INSERT INTO evaluacion (
muestra_id, sesion_participante_id, intensidades, otras_notas
) VALUES (
test_muestra_id, test_part_id,
'{"fragancia":{"descriptiva":5,"afectiva":5}}'::jsonb,
long_text
);
SELECT otras_notas INTO stored_text
FROM evaluacion
WHERE muestra_id = test_muestra_id;
IF stored_text = long_text THEN
RAISE NOTICE ' ✓ Acepta y almacena texto largo (% caracteres)', length(stored_text);
ELSE
RAISE EXCEPTION ' ✗ Texto almacenado no coincide';
END IF;
EXCEPTION WHEN OTHERS THEN
RAISE EXCEPTION ' ✗ Falló con texto largo: %', SQLERRM;
END;
-- Cleanup
DELETE FROM sesion WHERE id = test_sesion_id;
DELETE FROM auth.users WHERE id = test_user_id;
RAISE NOTICE '✓ Texto largo funciona correctamente';
END $$;
\echo ''
\echo '=========================================='
\echo 'Tests de Casos Límite completados'
\echo '=========================================='