-- ============================================ -- rioCata - Tests de Validación -- ============================================ -- Este script ejecuta tests para validar: -- 1. Estructura de tablas y constraints -- 2. Triggers (updated_at, puntaje_final) -- 3. Validaciones de arrays y JSONB -- 4. Queries típicas -- 5. Funciones auxiliares -- ============================================ \echo '==========================================' \echo 'rioCata - Test Suite' \echo '==========================================' \echo '' -- ============================================ -- TEST 1: Verificar que las tablas existen -- ============================================ \echo '[TEST 1] Verificando existencia de tablas...' DO $$ DECLARE tabla_count int; BEGIN SELECT COUNT(*) INTO tabla_count FROM information_schema.tables WHERE table_schema = 'public' AND table_name IN ('sesion', 'sesion_participante', 'muestra', 'evaluacion'); IF tabla_count = 4 THEN RAISE NOTICE '✓ Todas las tablas principales existen (4/4)'; ELSE RAISE EXCEPTION '✗ Faltan tablas. Encontradas: %/4', tabla_count; END IF; -- Verificar tabla auth.users SELECT COUNT(*) INTO tabla_count FROM information_schema.tables WHERE table_schema = 'auth' AND table_name = 'users'; IF tabla_count = 1 THEN RAISE NOTICE '✓ Tabla auth.users existe'; ELSE RAISE EXCEPTION '✗ Tabla auth.users no existe'; END IF; END $$; \echo '' -- ============================================ -- TEST 2: Verificar tipo ENUM defecto_tipo -- ============================================ \echo '[TEST 2] Verificando tipo ENUM defecto_tipo...' DO $$ DECLARE enum_exists boolean; BEGIN SELECT EXISTS ( SELECT 1 FROM pg_type WHERE typname = 'defecto_tipo' ) INTO enum_exists; IF enum_exists THEN RAISE NOTICE '✓ Tipo ENUM defecto_tipo existe'; ELSE RAISE EXCEPTION '✗ Tipo ENUM defecto_tipo no existe'; END IF; END $$; \echo '' -- ============================================ -- TEST 3: Verificar triggers -- ============================================ \echo '[TEST 3] Verificando triggers...' DO $$ DECLARE trigger_count int; BEGIN SELECT COUNT(*) INTO trigger_count FROM information_schema.triggers WHERE trigger_name IN ('trg_eval_updated_at', 'trg_eval_score_bi'); IF trigger_count = 2 THEN RAISE NOTICE '✓ Todos los triggers existen (2/2)'; ELSE RAISE EXCEPTION '✗ Faltan triggers. Encontrados: %/2', trigger_count; END IF; END $$; \echo '' -- ============================================ -- TEST 4: Verificar índices -- ============================================ \echo '[TEST 4] Verificando índices...' DO $$ DECLARE index_count int; BEGIN SELECT COUNT(*) INTO index_count FROM pg_indexes WHERE schemaname = 'public' AND indexname LIKE 'idx_%'; IF index_count >= 15 THEN RAISE NOTICE '✓ Índices creados correctamente (% encontrados)', index_count; ELSE RAISE WARNING '⚠ Se esperaban al menos 15 índices, se encontraron: %', index_count; END IF; END $$; \echo '' -- ============================================ -- TEST 5: Test de constraint - tazas_no_uniformes válidas -- ============================================ \echo '[TEST 5] Validando constraint tazas_no_uniformes (valores 1-5)...' DO $$ BEGIN -- Intentar insertar valor inválido (6) BEGIN INSERT INTO evaluacion ( muestra_id, sesion_participante_id, intensidades, tazas_no_uniformes ) VALUES ( 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '{"fragancia":{"descriptiva":1,"afectiva":1}}'::jsonb, ARRAY[6]::smallint[] ); RAISE EXCEPTION '✗ El constraint tazas_no_uniformes NO funcionó (aceptó valor 6)'; EXCEPTION WHEN check_violation THEN RAISE NOTICE '✓ Constraint tazas_no_uniformes funciona correctamente'; END; END $$; \echo '' -- ============================================ -- TEST 6: Test de constraint - gustos_predominantes (máximo 2) -- ============================================ \echo '[TEST 6] Validando constraint gustos_predominantes (máximo 2 elementos)...' DO $$ BEGIN -- Intentar insertar 3 gustos (debería fallar) BEGIN INSERT INTO evaluacion ( muestra_id, sesion_participante_id, intensidades, gustos_predominantes ) VALUES ( 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '{"fragancia":{"descriptiva":1,"afectiva":1}}'::jsonb, ARRAY['Ácido', 'Dulce', 'Amargo']::text[] ); RAISE EXCEPTION '✗ El constraint gustos_predominantes NO funcionó (aceptó 3 elementos)'; EXCEPTION WHEN check_violation THEN RAISE NOTICE '✓ Constraint gustos_predominantes funciona correctamente'; END; END $$; \echo '' -- ============================================ -- TEST 7: Test de constraint - sensacion_en_boca (valores válidos) -- ============================================ \echo '[TEST 7] Validando constraint sensacion_en_boca (valores permitidos)...' DO $$ BEGIN -- Intentar insertar valor no permitido BEGIN INSERT INTO evaluacion ( muestra_id, sesion_participante_id, intensidades, sensacion_en_boca ) VALUES ( 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '{"fragancia":{"descriptiva":1,"afectiva":1}}'::jsonb, ARRAY['Raro', 'Extraño']::text[] ); RAISE EXCEPTION '✗ El constraint sensacion_en_boca NO funcionó'; EXCEPTION WHEN check_violation THEN RAISE NOTICE '✓ Constraint sensacion_en_boca funciona correctamente'; END; END $$; \echo '' -- ============================================ -- TEST 8: Test de constraint - rangos de intensidades -- ============================================ \echo '[TEST 8] Validando constraint rangos de intensidades (descriptiva 1-15, afectiva 1-10)...' DO $$ BEGIN -- Intentar insertar descriptiva > 15 BEGIN INSERT INTO evaluacion ( muestra_id, sesion_participante_id, intensidades ) VALUES ( 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '{"fragancia":{"descriptiva":20,"afectiva":5}}'::jsonb ); RAISE EXCEPTION '✗ El constraint de rangos NO funcionó (aceptó descriptiva=20)'; EXCEPTION WHEN check_violation THEN RAISE NOTICE '✓ Constraint rangos de intensidades funciona (descriptiva)'; END; -- Intentar insertar afectiva > 10 BEGIN INSERT INTO evaluacion ( muestra_id, sesion_participante_id, intensidades ) VALUES ( 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '{"fragancia":{"descriptiva":5,"afectiva":15}}'::jsonb ); RAISE EXCEPTION '✗ El constraint de rangos NO funcionó (aceptó afectiva=15)'; EXCEPTION WHEN check_violation THEN RAISE NOTICE '✓ Constraint rangos de intensidades funciona (afectiva)'; END; END $$; \echo '' -- ============================================ -- TEST 9: Test de trigger - puntaje_final se calcula automáticamente -- ============================================ \echo '[TEST 9] Validando trigger de cálculo automático de puntaje_final...' DO $$ DECLARE puntaje_calculado int; puntaje_esperado int := 75; -- Suma de afectivos: 9+9+10+9+9+10+9+10 = 75 BEGIN -- Verificar evaluación existente SELECT puntaje_final INTO puntaje_calculado FROM evaluacion WHERE muestra_id = 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee' AND sesion_participante_id = 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'; IF puntaje_calculado = puntaje_esperado THEN RAISE NOTICE '✓ Trigger puntaje_final funciona correctamente (% = %)', puntaje_calculado, puntaje_esperado; ELSE RAISE EXCEPTION '✗ Puntaje calculado (%) no coincide con esperado (%)', puntaje_calculado, puntaje_esperado; END IF; END $$; \echo '' -- ============================================ -- TEST 10: Test de constraint UNIQUE - una evaluación por participante por muestra -- ============================================ \echo '[TEST 10] Validando constraint UNIQUE (una evaluación por participante/muestra)...' DO $$ BEGIN -- Intentar insertar evaluación duplicada BEGIN INSERT INTO evaluacion ( muestra_id, sesion_participante_id, intensidades ) VALUES ( 'eeeeeeee-eeee-eeee-eeee-eeeeeeeeeeee', 'bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', '{"fragancia":{"descriptiva":1,"afectiva":1}}'::jsonb ); RAISE EXCEPTION '✗ El constraint UNIQUE NO funcionó (permitió duplicado)'; EXCEPTION WHEN unique_violation THEN RAISE NOTICE '✓ Constraint UNIQUE funciona correctamente'; END; END $$; \echo '' -- ============================================ -- TEST 11: Query típica - Promedio de parámetro afectivo -- ============================================ \echo '[TEST 11] Probando query: Promedio de dulzor afectivo por sesión...' DO $$ DECLARE avg_dulzor numeric; BEGIN SELECT AVG( ((e.intensidades->'dulzor'->>'afectiva')::int) ) INTO avg_dulzor FROM sesion s JOIN muestra m ON m.sesion_id = s.id JOIN evaluacion e ON e.muestra_id = m.id WHERE s.id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'; IF avg_dulzor IS NOT NULL THEN RAISE NOTICE '✓ Query promedio funciona. Dulzor promedio: %', ROUND(avg_dulzor, 2); ELSE RAISE EXCEPTION '✗ Query promedio falló'; END IF; END $$; \echo '' -- ============================================ -- TEST 12: Query típica - Buscar por defecto -- ============================================ \echo '[TEST 12] Probando query: Buscar evaluaciones con defecto Fenólico...' DO $$ DECLARE defecto_count int; BEGIN SELECT COUNT(*) INTO defecto_count FROM evaluacion WHERE defecto = 'Fenólico'; IF defecto_count > 0 THEN RAISE NOTICE '✓ Query por defecto funciona. Evaluaciones con defecto Fenólico: %', defecto_count; ELSE RAISE WARNING '⚠ No se encontraron evaluaciones con defecto Fenólico (puede ser normal)'; END IF; END $$; \echo '' -- ============================================ -- TEST 13: Query típica - Buscar por taza defectuosa específica -- ============================================ \echo '[TEST 13] Probando query: Buscar evaluaciones donde taza 5 fue defectuosa...' DO $$ DECLARE taza_count int; BEGIN SELECT COUNT(*) INTO taza_count FROM evaluacion WHERE tazas_defectuosas @> ARRAY[5]::smallint[]; IF taza_count > 0 THEN RAISE NOTICE '✓ Query con array @> funciona. Evaluaciones con taza 5 defectuosa: %', taza_count; ELSE RAISE WARNING '⚠ No se encontraron evaluaciones con taza 5 defectuosa'; END IF; END $$; \echo '' -- ============================================ -- TEST 14: Query típica - Top muestras por puntaje -- ============================================ \echo '[TEST 14] Probando query: Top 3 muestras por puntaje final...' DO $$ DECLARE top_muestra text; top_puntaje int; BEGIN SELECT m.codigo, e.puntaje_final INTO top_muestra, top_puntaje FROM muestra m JOIN evaluacion e ON e.muestra_id = m.id JOIN sesion_participante sp ON sp.id = e.sesion_participante_id WHERE m.sesion_id = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa' ORDER BY e.puntaje_final DESC LIMIT 1; IF top_muestra IS NOT NULL THEN RAISE NOTICE '✓ Query top muestras funciona. Mejor muestra: % (puntaje: %)', top_muestra, top_puntaje; ELSE RAISE EXCEPTION '✗ Query top muestras falló'; END IF; END $$; \echo '' -- ============================================ -- TEST 15: Función auxiliar - get_promedio_parametro_afectivo -- ============================================ \echo '[TEST 15] Probando función: get_promedio_parametro_afectivo...' DO $$ DECLARE avg_acidez numeric; BEGIN SELECT get_promedio_parametro_afectivo( 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'acidez' ) INTO avg_acidez; IF avg_acidez IS NOT NULL THEN RAISE NOTICE '✓ Función get_promedio_parametro_afectivo funciona. Acidez promedio: %', ROUND(avg_acidez, 2); ELSE RAISE EXCEPTION '✗ Función get_promedio_parametro_afectivo falló'; END IF; END $$; \echo '' -- ============================================ -- TEST 16: Función auxiliar - get_top_muestras -- ============================================ \echo '[TEST 16] Probando función: get_top_muestras...' DO $$ DECLARE resultado record; count_resultados int := 0; BEGIN FOR resultado IN SELECT * FROM get_top_muestras('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 3) LOOP count_resultados := count_resultados + 1; RAISE NOTICE ' - %: % puntos (catador: %)', resultado.muestra_codigo, resultado.puntaje_final, resultado.catador_nombre; END LOOP; IF count_resultados > 0 THEN RAISE NOTICE '✓ Función get_top_muestras funciona. Resultados: %', count_resultados; ELSE RAISE EXCEPTION '✗ Función get_top_muestras no devolvió resultados'; END IF; END $$; \echo '' -- ============================================ -- TEST 17: Query con índice funcional - filtrar por acidez afectiva -- ============================================ \echo '[TEST 17] Probando query con índice funcional: acidez afectiva >= 8...' DO $$ DECLARE count_acidez int; BEGIN SELECT COUNT(*) INTO count_acidez FROM evaluacion WHERE ((intensidades->'acidez'->>'afectiva')::int) >= 8; IF count_acidez >= 0 THEN RAISE NOTICE '✓ Query con índice funcional funciona. Evaluaciones con acidez >= 8: %', count_acidez; ELSE RAISE EXCEPTION '✗ Query con índice funcional falló'; END IF; END $$; \echo '' -- ============================================ -- TEST 18: Validar datos de prueba cargados -- ============================================ \echo '[TEST 18] Validando que los datos de prueba se cargaron correctamente...' DO $$ DECLARE count_users int; count_sesiones int; count_muestras int; count_evaluaciones int; BEGIN SELECT COUNT(*) INTO count_users FROM auth.users; SELECT COUNT(*) INTO count_sesiones FROM sesion; SELECT COUNT(*) INTO count_muestras FROM muestra; SELECT COUNT(*) INTO count_evaluaciones FROM evaluacion; IF count_users >= 3 AND count_sesiones >= 1 AND count_muestras >= 3 AND count_evaluaciones >= 5 THEN RAISE NOTICE '✓ Datos de prueba cargados:'; RAISE NOTICE ' - Usuarios: %', count_users; RAISE NOTICE ' - Sesiones: %', count_sesiones; RAISE NOTICE ' - Muestras: %', count_muestras; RAISE NOTICE ' - Evaluaciones: %', count_evaluaciones; ELSE RAISE WARNING '⚠ Algunos datos de prueba pueden faltar:'; RAISE WARNING ' - Usuarios: % (esperado: >= 3)', count_users; RAISE WARNING ' - Sesiones: % (esperado: >= 1)', count_sesiones; RAISE WARNING ' - Muestras: % (esperado: >= 3)', count_muestras; RAISE WARNING ' - Evaluaciones: % (esperado: >= 5)', count_evaluaciones; END IF; END $$; \echo '' \echo '==========================================' \echo 'Tests completados' \echo '==========================================' \echo '' \echo 'Ejecuta queries de ejemplo con:' \echo ' \i postgres/tests/example_queries.sql' \echo ''