#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 🧪 SCRIPT DE TESTING COMPLETO - DETECTOR DE LOBBIES Múltiples formas de evaluar el modelo: 1. Test Rápido (10 casos) 2. Test Completo (100 casos del dataset) 3. Test Interactivo (tus propios textos) 4. Test de Rendimiento 5. Análisis de "confianza" (proxy: longitud/variedad de entidades detectadas) Nota: spaCy NER no expone scores de entidad directamente en uso estándar. """ import spacy import time import sys # ============================================================================== # CONFIGURACIÓN # ============================================================================== MODELO_PATH = "/mnt/data/Aritz_Spacy_2/modelo_SOLO_LOBBIES" THRESHOLD = 0.65 # (Placeholder) No se usa directamente en spaCy NER estándar # ============================================================================== # DATASET: 100 FRASES PARA TEST COMPLETO # ============================================================================== DATASET_100 = [ {"id": 1, "texto": "La CEOE pidió al Gobierno cambios en la reforma laboral antes de su votación.", "expected_lobby": 1}, {"id": 2, "texto": "Farmaindustria defendió que la nueva norma de precios no afectará al acceso a medicamentos.", "expected_lobby": 1}, {"id": 3, "texto": "ANFAC reclamó un plan de ayudas para acelerar la electrificación del parque móvil.", "expected_lobby": 1}, {"id": 4, "texto": "Greenpeace criticó el retraso en la aprobación del plan de transición energética.", "expected_lobby": 1}, {"id": 5, "texto": "Amnistía Internacional solicitó garantías de derechos en el nuevo pacto migratorio.", "expected_lobby": 1}, {"id": 6, "texto": "FACUA anunció una denuncia por cláusulas abusivas en contratos de energía.", "expected_lobby": 1}, {"id": 7, "texto": "La Asociación Española de Banca valoró positivamente la estabilidad regulatoria.", "expected_lobby": 1}, {"id": 8, "texto": "La patronal del metal advirtió de riesgos para el empleo si sube el coste eléctrico.", "expected_lobby": 1}, {"id": 9, "texto": "La Confederación de Hostelería pidió ampliar los horarios en temporada alta.", "expected_lobby": 1}, {"id": 10, "texto": "La Asociación de Constructores propuso simplificar licencias para vivienda asequible.", "expected_lobby": 1}, {"id": 11, "texto": "La Cámara de Comercio apoyó incentivos fiscales para pymes exportadoras.", "expected_lobby": 1}, {"id": 12, "texto": "La Asociación de Productores de Energías Renovables pidió acelerar permisos.", "expected_lobby": 1}, {"id": 13, "texto": "La Asociación de Transporte por Carretera criticó el aumento de peajes.", "expected_lobby": 1}, {"id": 14, "texto": "La Federación de Industria Alimentaria pidió revisar el impuesto al azúcar.", "expected_lobby": 1}, {"id": 15, "texto": "La Asociación de Editores reclamó medidas contra la piratería digital.", "expected_lobby": 1}, {"id": 16, "texto": "La Asociación de Fabricantes de Bebidas pidió claridad sobre el etiquetado nutricional.", "expected_lobby": 1}, {"id": 17, "texto": "La patronal turística alertó de falta de personal en destinos costeros.", "expected_lobby": 1}, {"id": 18, "texto": "La asociación de aseguradoras propuso cambios en el baremo de accidentes.", "expected_lobby": 1}, {"id": 19, "texto": "La Asociación de Supermercados pidió estabilidad en la cadena de suministro.", "expected_lobby": 1}, {"id": 20, "texto": "La alianza empresarial por la digitalización presentó un paquete de propuestas.", "expected_lobby": 1}, {"id": 21, "texto": "El lobby agrario presionó para ampliar el periodo de ayudas europeas.", "expected_lobby": 1}, {"id": 22, "texto": "La federación de cooperativas defendió el modelo frente a la nueva ley.", "expected_lobby": 1}, {"id": 23, "texto": "La organización ecologista SEO/BirdLife pidió proteger zonas de nidificación.", "expected_lobby": 1}, {"id": 24, "texto": "La asociación de fabricantes de cemento pidió un calendario realista de descarbonización.", "expected_lobby": 1}, {"id": 25, "texto": "La plataforma de empresas tecnológicas solicitó un marco común de IA.", "expected_lobby": 1}, {"id": 26, "texto": "La Asociación Española de Distribuidores de Automoción pidió rebajar el IVA de reparación.", "expected_lobby": 1}, {"id": 27, "texto": "La asociación de promotores inmobiliarios criticó el tope a los alquileres.", "expected_lobby": 1}, {"id": 28, "texto": "La federación de farmacéuticos pidió reforzar el suministro de medicamentos esenciales.", "expected_lobby": 1}, {"id": 29, "texto": "La asociación de exportadores reclamó agilizar aduanas en puertos clave.", "expected_lobby": 1}, {"id": 30, "texto": "La patronal del sector textil pidió apoyo ante la competencia asiática.", "expected_lobby": 1}, {"id": 31, "texto": "El sindicato convocó una asamblea para decidir nuevas movilizaciones.", "expected_lobby": 0}, {"id": 32, "texto": "El ministro anunció un paquete de medidas para abaratar la factura de la luz.", "expected_lobby": 0}, {"id": 33, "texto": "La comisión parlamentaria aprobó el calendario de comparecencias.", "expected_lobby": 0}, {"id": 34, "texto": "La policía detuvo a dos personas por fraude en subvenciones públicas.", "expected_lobby": 0}, {"id": 35, "texto": "El ayuntamiento abrió un nuevo centro de atención ciudadana en el distrito.", "expected_lobby": 0}, {"id": 36, "texto": "La universidad presentó un estudio sobre hábitos de lectura en adolescentes.", "expected_lobby": 0}, {"id": 37, "texto": "El tribunal archivó la causa por falta de indicios suficientes.", "expected_lobby": 0}, {"id": 38, "texto": "El banco central revisó a la baja la previsión de crecimiento para 2026.", "expected_lobby": 0}, {"id": 39, "texto": "La agencia meteorológica activó avisos por lluvias intensas en el litoral.", "expected_lobby": 0}, {"id": 40, "texto": "La selección ganó el partido con un gol en el minuto noventa.", "expected_lobby": 0}, {"id": 41, "texto": "El hospital incorporó un nuevo equipo de diagnóstico por imagen.", "expected_lobby": 0}, {"id": 42, "texto": "El portavoz negó irregularidades y pidió prudencia hasta conocer el informe.", "expected_lobby": 0}, {"id": 43, "texto": "El pleno municipal debatió la ordenanza de terrazas durante tres horas.", "expected_lobby": 0}, {"id": 44, "texto": "La fiscalía solicitó nuevas diligencias para completar la investigación.", "expected_lobby": 0}, {"id": 45, "texto": "El museo inauguró una exposición sobre fotografía contemporánea.", "expected_lobby": 0}, {"id": 46, "texto": "El Gobierno regional aprobó el presupuesto con apoyo de dos partidos.", "expected_lobby": 0}, {"id": 47, "texto": "La oposición criticó la falta de transparencia en el contrato de obras.", "expected_lobby": 0}, {"id": 48, "texto": "El juez fijó fecha para la vista oral del caso.", "expected_lobby": 0}, {"id": 49, "texto": "La empresa anunció resultados trimestrales por encima de lo esperado.", "expected_lobby": 0}, {"id": 50, "texto": "La inflación interanual se moderó por la caída del precio del combustible.", "expected_lobby": 0}, {"id": 51, "texto": "Iberdrola trasladó al regulador sus alegaciones sobre el nuevo marco de redes.", "expected_lobby": 1}, {"id": 52, "texto": "Repsol defendió su estrategia de biocombustibles ante el cambio normativo.", "expected_lobby": 1}, {"id": 53, "texto": "Telefónica pidió armonización europea para el despliegue de 5G.", "expected_lobby": 1}, {"id": 54, "texto": "Santander solicitó claridad sobre los requisitos de capital en banca minorista.", "expected_lobby": 1}, {"id": 55, "texto": "BBVA advirtió de impactos en crédito si se endurece la regulación.", "expected_lobby": 1}, {"id": 56, "texto": "Endesa pidió extender los plazos de conexión para proyectos industriales.", "expected_lobby": 1}, {"id": 57, "texto": "Naturgy presentó propuestas sobre mercados de capacidad y almacenamiento.", "expected_lobby": 1}, {"id": 58, "texto": "La Asociación Española de Hidrógeno pidió incentivos para electrolizadores.", "expected_lobby": 1}, {"id": 59, "texto": "La Plataforma por un Internet Seguro reclamó obligaciones de trazabilidad.", "expected_lobby": 1}, {"id": 60, "texto": "La Asociación Nacional de Grandes Empresas de Distribución defendió la libre competencia.", "expected_lobby": 1}, {"id": 61, "texto": "El colegio profesional de médicos pidió más plazas MIR y mejores contratos.", "expected_lobby": 1}, {"id": 62, "texto": "La federación de enseñanza concertada reclamó seguridad jurídica en la financiación.", "expected_lobby": 1}, {"id": 63, "texto": "La Asociación de Startups solicitó una ventanilla única para trámites.", "expected_lobby": 1}, {"id": 64, "texto": "La industria del videojuego pidió incentivos fiscales para producción local.", "expected_lobby": 1}, {"id": 65, "texto": "La patronal de renovables denunció cuellos de botella en la red eléctrica.", "expected_lobby": 1}, {"id": 66, "texto": "La asociación de productores de aceite pidió reforzar controles de calidad.", "expected_lobby": 1}, {"id": 67, "texto": "La confederación de regantes reclamó inversiones en modernización de infraestructuras.", "expected_lobby": 1}, {"id": 68, "texto": "La asociación de fabricantes de electrónica pidió reducir aranceles a componentes.", "expected_lobby": 1}, {"id": 69, "texto": "La federación de transporte urbano pidió financiación estable para autobuses.", "expected_lobby": 1}, {"id": 70, "texto": "La asociación de hoteleros propuso un plan contra la estacionalidad.", "expected_lobby": 1}, {"id": 71, "texto": "El presidente compareció tras el Consejo de Ministros sin admitir preguntas.", "expected_lobby": 0}, {"id": 72, "texto": "La portavoz explicó que el decreto se publicará en el BOE mañana.", "expected_lobby": 0}, {"id": 73, "texto": "La policía local reforzó controles de tráfico durante el puente.", "expected_lobby": 0}, {"id": 74, "texto": "La audiencia provincial ordenó repetir el juicio por defectos procesales.", "expected_lobby": 0}, {"id": 75, "texto": "El informe anual destacó mejoras en transparencia administrativa.", "expected_lobby": 0}, {"id": 76, "texto": "La ciudad abrió un proceso participativo para el nuevo plan de movilidad.", "expected_lobby": 0}, {"id": 77, "texto": "El sistema de transporte público anunció cambios en horarios nocturnos.", "expected_lobby": 0}, {"id": 78, "texto": "El ministerio publicó una guía de buenas prácticas para contratación.", "expected_lobby": 0}, {"id": 79, "texto": "Un incendio obligó a evacuar a cien vecinos por prevención.", "expected_lobby": 0}, {"id": 80, "texto": "La compañía ferroviaria restableció la circulación tras una avería.", "expected_lobby": 0}, {"id": 81, "texto": "La Asociación de Consumidores Europeos pidió más protección de datos en apps.", "expected_lobby": 1}, {"id": 82, "texto": "La International Chamber of Commerce publicó recomendaciones sobre comercio digital.", "expected_lobby": 1}, {"id": 83, "texto": "La European Consumer Organisation (BEUC) criticó la falta de sanciones efectivas.", "expected_lobby": 1}, {"id": 84, "texto": "La Organización Internacional de Empleadores pidió flexibilidad en la normativa laboral.", "expected_lobby": 1}, {"id": 85, "texto": "La asociación de fabricantes de plástico pidió objetivos realistas de reciclaje.", "expected_lobby": 1}, {"id": 86, "texto": "La federación de energía eólica propuso subastas con criterios de red.", "expected_lobby": 1}, {"id": 87, "texto": "La asociación del sector químico pidió simplificar el registro de sustancias.", "expected_lobby": 1}, {"id": 88, "texto": "La industria del acero solicitó ayudas por costes de CO2.", "expected_lobby": 1}, {"id": 89, "texto": "La patronal de telecomunicaciones pidió reducir tasas por espectro.", "expected_lobby": 1}, {"id": 90, "texto": "La asociación de fintech pidió reglas claras para open banking.", "expected_lobby": 1}, {"id": 91, "texto": "El Parlamento debatió una moción sobre vivienda sin acuerdo final.", "expected_lobby": 0}, {"id": 92, "texto": "La ministra respondió a la interpelación con cifras de ejecución presupuestaria.", "expected_lobby": 0}, {"id": 93, "texto": "El portavoz del partido anunció primarias para elegir candidato.", "expected_lobby": 0}, {"id": 94, "texto": "La comisión de investigación citó a varios ex altos cargos.", "expected_lobby": 0}, {"id": 95, "texto": "El informe del regulador señaló incumplimientos en varios contratos.", "expected_lobby": 0}, {"id": 96, "texto": "El ayuntamiento aprobó un plan de arbolado urbano para cinco años.", "expected_lobby": 0}, {"id": 97, "texto": "El servicio de emergencias atendió más de mil llamadas durante la tormenta.", "expected_lobby": 0}, {"id": 98, "texto": "La empresa municipal licitó el mantenimiento de alumbrado por cuatro años.", "expected_lobby": 0}, {"id": 99, "texto": "El tribunal constitucional admitió a trámite un recurso por unanimidad.", "expected_lobby": 0}, {"id": 100, "texto": "El gobierno local presentó un nuevo portal de datos abiertos.", "expected_lobby": 0}, ] # ============================================================================== # UTILIDADES # ============================================================================== def cargar_modelo(): print("\n⏳ Cargando modelo...") try: nlp = spacy.load(MODELO_PATH) print("✅ Modelo cargado correctamente\n") return nlp except Exception as e: print(f"❌ Error cargando el modelo: {e}") return None def extraer_lobbies(doc): """Devuelve lista de entidades detectadas (texto)""" return [ent.text for ent in doc.ents if ent.label_ == "LOBBY"] # ============================================================================== # TEST 1: PRUEBA RÁPIDA (10 casos) # ============================================================================== def test_rapido(): """Test rápido con 10 casos representativos""" print("="*80) print("🚀 TEST RÁPIDO - 10 Casos Representativos") print("="*80) nlp = cargar_modelo() if nlp is None: return casos = [ {"texto": "La CEOE critica duramente la reforma laboral propuesta por el Gobierno", "esperado": ["CEOE"], "tipo": "Organización empresarial"}, {"texto": "Telefónica invertirá 1000 millones en infraestructura de fibra óptica", "esperado": ["Telefónica"], "tipo": "Gran empresa"}, {"texto": "El BBVA y Banco Santander lideran el ranking de beneficios bancarios", "esperado": ["BBVA", "Banco Santander"], "tipo": "Múltiples lobbies"}, {"texto": "CEPYME se reúne con el Ministerio de Economía para discutir ayudas", "esperado": ["CEPYME"], "tipo": "Contexto con ministerio"}, {"texto": "Iberdrola y Endesa rechazan el tope al precio de la electricidad", "esperado": ["Iberdrola", "Endesa"], "tipo": "Múltiples empresas"}, {"texto": "Google España pide claridad en la regulación de plataformas digitales", "esperado": ["Google España"], "tipo": "Tecnología"}, {"texto": "El Ministerio de Economía anuncia nuevas medidas fiscales", "esperado": [], "tipo": "NO lobby (ministerio)"}, {"texto": "El PSOE presenta una moción junto al PP en el Congreso", "esperado": [], "tipo": "NO lobby (partidos)"}, {"texto": "Fedea publica un informe crítico sobre las pensiones", "esperado": ["Fedea"], "tipo": "Think tank"}, {"texto": "CEOE, CEPYME y Foment coordinan su posición ante Bruselas", "esperado": ["CEOE", "CEPYME", "Foment"], "tipo": "Múltiples organizaciones"}, ] aciertos = 0 total = len(casos) for i, caso in enumerate(casos, 1): print(f"📝 Caso {i}/{total}: {caso['tipo']}") print(f" Texto: {caso['texto'][:70]}...") doc = nlp(caso["texto"]) detectados = extraer_lobbies(doc) esperados = caso["esperado"] detectados_set = set(detectados) esperados_set = set(esperados) correctos = detectados_set & esperados_set falsos_pos = detectados_set - esperados_set no_detectados = esperados_set - detectados_set perfecto = (not falsos_pos and not no_detectados) if perfecto: print(" ✅ PERFECTO") aciertos += 1 else: print(" ⚠️ Parcial") print(f" Esperado: {', '.join(esperados) if esperados else '(ninguno)'}") print(f" Detectado: {', '.join(detectados) if detectados else '(ninguno)'}") if correctos: print(f" ✅ Correcto: {', '.join(sorted(correctos))}") if no_detectados: print(f" ❌ No detectado: {', '.join(sorted(no_detectados))}") if falsos_pos: print(f" ⚠️ Falso +: {', '.join(sorted(falsos_pos))}") print() accuracy = (aciertos / total) * 100 print("="*80) print(f"📊 RESULTADO: {aciertos}/{total} casos perfectos ({accuracy:.1f}%)") print("="*80) if accuracy >= 80: print("🌟 EXCELENTE - Modelo funciona muy bien") elif accuracy >= 60: print("✅ BUENO - Modelo funcional") else: print("⚠️ MEJORABLE - Revisar configuración") # ============================================================================== # TEST 2: EVALUACIÓN COMPLETA (100 casos) # ============================================================================== def test_completo(): """Ejecuta la evaluación completa de 100 casos (binario: hay/no hay lobby)""" print("="*80) print("🧪 TEST COMPLETO - 100 Casos (Dataset incluido)") print("="*80) nlp = cargar_modelo() if nlp is None: return tp = fp = tn = fn = 0 ejemplos_fp = [] ejemplos_fn = [] for item in DATASET_100: doc = nlp(item["texto"]) detectados = extraer_lobbies(doc) pred = 1 if len(detectados) > 0 else 0 gold = int(item["expected_lobby"]) if pred == 1 and gold == 1: tp += 1 elif pred == 1 and gold == 0: fp += 1 if len(ejemplos_fp) < 10: ejemplos_fp.append((item["id"], item["texto"], detectados)) elif pred == 0 and gold == 0: tn += 1 elif pred == 0 and gold == 1: fn += 1 if len(ejemplos_fn) < 10: ejemplos_fn.append((item["id"], item["texto"], detectados)) # Métricas precision = tp / (tp + fp) if (tp + fp) else 0.0 recall = tp / (tp + fn) if (tp + fn) else 0.0 f1 = (2 * precision * recall / (precision + recall)) if (precision + recall) else 0.0 accuracy = (tp + tn) / (tp + tn + fp + fn) if (tp + tn + fp + fn) else 0.0 print("\n📊 MÉTRICAS (detección binaria: alguna entidad LOBBY en la frase)") print(f" TP: {tp} FP: {fp} TN: {tn} FN: {fn}") print(f" Precision: {precision:.3f}") print(f" Recall: {recall:.3f}") print(f" F1: {f1:.3f}") print(f" Accuracy: {accuracy:.3f}") if ejemplos_fp: print("\n⚠️ EJEMPLOS FALSOS POSITIVOS (hasta 10):") for _id, txt, det in ejemplos_fp: print(f" - ID {_id}: {txt}") print(f" Detectado: {', '.join(det) if det else '(ninguno)'}") if ejemplos_fn: print("\n❌ EJEMPLOS FALSOS NEGATIVOS (hasta 10):") for _id, txt, det in ejemplos_fn: print(f" - ID {_id}: {txt}") print(f" Detectado: {', '.join(det) if det else '(ninguno)'}") print("\n✅ Test completo finalizado.") # ============================================================================== # TEST 3: TEST INTERACTIVO # ============================================================================== def test_interactivo(): """Permite probar con tus propios textos""" print("="*80) print("💬 TEST INTERACTIVO - Prueba tus propios textos") print("="*80) nlp = cargar_modelo() if nlp is None: return print("Escribe textos para analizar (o 'salir' para terminar):") print("="*80) while True: try: texto = input("\n📝 Texto: ").strip() except KeyboardInterrupt: print("\n\n👋 ¡Hasta luego!") break if texto.lower() in ["salir", "exit", "quit", ""]: print("\n👋 ¡Hasta luego!") break doc = nlp(texto) lobbies = [ent for ent in doc.ents if ent.label_ == "LOBBY"] if lobbies: print(f"\n🎯 Lobbies detectados ({len(lobbies)}):") for ent in lobbies: print(f" • {ent.text} ({ent.label_})") else: print("\n❌ No se detectaron lobbies") # ============================================================================== # TEST 4: TEST DE RENDIMIENTO # ============================================================================== def test_rendimiento(): """Mide velocidad del modelo""" print("="*80) print("⚡ TEST DE RENDIMIENTO") print("="*80) nlp = cargar_modelo() if nlp is None: return textos = [ "La CEOE critica la reforma laboral del Gobierno", "Telefónica invertirá millones en infraestructura digital", "El BBVA y Santander lideran el sector bancario español", "Iberdrola anuncia inversiones en energías renovables", "CEPYME solicita ayudas para las pymes españolas", ] * 20 # 100 textos print(f"📊 Procesando {len(textos)} textos...") start = time.time() total_ents = 0 for texto in textos: doc = nlp(texto) total_ents += len([ent for ent in doc.ents if ent.label_ == "LOBBY"]) end = time.time() tiempo_total = end - start tiempo_por_texto = (tiempo_total / len(textos)) * 1000 textos_por_segundo = len(textos) / tiempo_total if tiempo_total else 0 print("\n⚡ RESULTADOS:") print(f" Tiempo total: {tiempo_total:.2f}s") print(f" Tiempo por texto: {tiempo_por_texto:.1f}ms") print(f" Textos por segundo: {textos_por_segundo:.1f}") print(f" Entidades LOBBY detectadas: {total_ents}") if tiempo_por_texto < 50: print("\n🚀 EXCELENTE - Muy rápido") elif tiempo_por_texto < 100: print("\n✅ BUENO - Velocidad aceptable") else: print("\n⚠️ LENTO - Considera optimizar") # ============================================================================== # TEST 5: ANÁLISIS "PROXY" (sin scores) # ============================================================================== def test_confianza(): """Analiza detecciones (no hay scores directos).""" print("="*80) print("📊 TEST DE CONFIANZA (proxy) - Entidades detectadas") print("="*80) nlp = cargar_modelo() if nlp is None: return casos = [ "La CEOE critica la reforma laboral", "Telefónica invertirá en infraestructura", "El Ministerio anuncia medidas fiscales", "Iberdrola lidera las inversiones renovables", "El PSOE presenta una moción en el Congreso", ] print("🔍 Analizando detecciones...\n") for texto in casos: doc = nlp(texto) lobbies = [ent for ent in doc.ents if ent.label_ == "LOBBY"] print(f"📝 {texto}") if lobbies: for ent in lobbies: print(f" ✅ {ent.text:30} → {ent.label_}") else: print(" ❌ No se detectaron lobbies") print() # ============================================================================== # MENÚ PRINCIPAL # ============================================================================== def mostrar_menu(): print("\n" + "="*80) print("🧪 SISTEMA DE TESTING - DETECTOR DE LOBBIES") print("="*80) print("\nElige una opción:") print("\n 1. 🚀 Test Rápido (10 casos representativos)") print(" 2. 🧪 Test Completo (100 casos - dataset incluido)") print(" 3. 💬 Test Interactivo (tus propios textos)") print(" 4. ⚡ Test de Rendimiento (velocidad)") print(" 5. 📊 Análisis (proxy)") print(" 6. 🎯 Ejecutar TODOS los tests") print(" 0. 🚪 Salir") print("\n" + "="*80) def main(): while True: mostrar_menu() try: opcion = input("\n👉 Opción: ").strip() except KeyboardInterrupt: print("\n\n👋 ¡Hasta luego!") break if opcion == "1": test_rapido() input("\n⏸️ Presiona Enter para continuar...") elif opcion == "2": test_completo() input("\n⏸️ Presiona Enter para continuar...") elif opcion == "3": test_interactivo() elif opcion == "4": test_rendimiento() input("\n⏸️ Presiona Enter para continuar...") elif opcion == "5": test_confianza() input("\n⏸️ Presiona Enter para continuar...") elif opcion == "6": print("\n🎯 Ejecutando TODOS los tests...\n") test_rapido() print("\n" + "="*80 + "\n") test_completo() print("\n" + "="*80 + "\n") test_rendimiento() print("\n" + "="*80 + "\n") test_confianza() input("\n⏸️ Presiona Enter para continuar...") elif opcion == "0": print("\n👋 ¡Hasta luego!") break else: print("\n❌ Opción no válida") if __name__ == "__main__": if len(sys.argv) > 1: if sys.argv[1] == "rapido": test_rapido() elif sys.argv[1] == "completo": test_completo() elif sys.argv[1] == "interactivo": test_interactivo() elif sys.argv[1] == "rendimiento": test_rendimiento() elif sys.argv[1] == "confianza": test_confianza() else: print("Opciones: rapido, completo, interactivo, rendimiento, confianza") else: main()