""" Tests unitaires pour HumanLogger Teste le formatage des messages, les emojis et les messages contextuels. """ import sys from pathlib import Path # Ajouter le répertoire parent au path sys.path.insert(0, str(Path(__file__).parent.parent.parent)) from geniusia2.gui.human_logger import HumanLogger def test_initialization(): """Test l'initialisation de HumanLogger""" print("Test 1: Initialisation...") logger = HumanLogger() # Vérifier que les événements "première fois" sont initialisés assert "workflow_detected" in logger.first_time_events assert "mode_change" in logger.first_time_events assert "pattern_detected" in logger.first_time_events assert "finetuning_started" in logger.first_time_events # Tous doivent être False au départ assert logger.first_time_events["workflow_detected"] is False assert logger.first_time_events["mode_change"] is False assert logger.first_time_events["pattern_detected"] is False assert logger.first_time_events["finetuning_started"] is False print("✓ Initialisation OK") def test_log_observation_format(): """Test le formatage des messages d'observation""" print("\nTest 2: Formatage log_observation...") logger = HumanLogger() # Test avec différentes fenêtres msg1 = logger.log_observation("click", "Calculator") assert "👀" in msg1, "L'emoji d'observation doit être présent" assert "Calculator" in msg1, "Le nom de la fenêtre doit être présent" assert "J'observe" in msg1, "Le message doit contenir 'J'observe'" msg2 = logger.log_observation("type", "Firefox") assert "👀" in msg2 assert "Firefox" in msg2 msg3 = logger.log_observation("scroll", "LibreOffice Writer") assert "👀" in msg3 assert "LibreOffice Writer" in msg3 print("✓ Formatage log_observation OK") def test_log_pattern_detected_emoji(): """Test l'emoji correct pour pattern détecté""" print("\nTest 3: Emoji log_pattern_detected...") logger = HumanLogger() msg = logger.log_pattern_detected(3, "Calculer 9/9") assert "🎯" in msg, "L'emoji de pattern doit être présent" assert "3 fois" in msg, "Le nombre de répétitions doit être présent" print("✓ Emoji log_pattern_detected OK") def test_log_pattern_detected_contextual(): """Test les messages contextuels pour pattern détecté""" print("\nTest 4: Messages contextuels log_pattern_detected...") logger = HumanLogger() # Première fois - doit inclure le contexte msg1 = logger.log_pattern_detected(3, "Calculer 9/9") assert "Je commence à apprendre" in msg1, "Le message contextuel doit être présent la première fois" assert logger.first_time_events["pattern_detected"] is True, "Le flag doit être mis à True" # Deuxième fois - ne doit pas inclure le contexte msg2 = logger.log_pattern_detected(4, "Ouvrir fichier") assert "Je commence à apprendre" not in msg2, "Le message contextuel ne doit pas être répété" print("✓ Messages contextuels log_pattern_detected OK") def test_log_workflow_learned_format(): """Test le formatage des messages de workflow appris""" print("\nTest 5: Formatage log_workflow_learned...") logger = HumanLogger() msg = logger.log_workflow_learned("Ouvrir facture", 5) assert "📚" in msg, "L'emoji de workflow doit être présent" assert "Ouvrir facture" in msg, "Le nom du workflow doit être présent" assert "5 observations" in msg, "Le nombre d'observations doit être présent" assert "J'apprends" in msg, "Le message doit contenir 'J'apprends'" print("✓ Formatage log_workflow_learned OK") def test_log_workflow_learned_contextual(): """Test les messages contextuels pour workflow appris""" print("\nTest 6: Messages contextuels log_workflow_learned...") logger = HumanLogger() # Première fois - doit inclure l'explication msg1 = logger.log_workflow_learned("Ouvrir facture", 5) assert "Un workflow est une séquence" in msg1, "L'explication doit être présente la première fois" assert logger.first_time_events["workflow_detected"] is True # Deuxième fois - ne doit pas inclure l'explication msg2 = logger.log_workflow_learned("Calculer total", 3) assert "Un workflow est une séquence" not in msg2, "L'explication ne doit pas être répétée" print("✓ Messages contextuels log_workflow_learned OK") def test_log_mode_change_format(): """Test le formatage des messages de changement de mode""" print("\nTest 7: Formatage log_mode_change...") logger = HumanLogger() # Test tous les modes msg_shadow = logger.log_mode_change("assist", "shadow") assert "✅" in msg_shadow, "L'emoji de succès doit être présent" assert "Observation" in msg_shadow, "Le nom du mode doit être traduit" msg_assist = logger.log_mode_change("shadow", "assist") assert "✅" in msg_assist assert "Suggestions" in msg_assist msg_copilot = logger.log_mode_change("assist", "copilot") assert "✅" in msg_copilot assert "Copilote" in msg_copilot msg_auto = logger.log_mode_change("copilot", "auto") assert "✅" in msg_auto assert "Autonome" in msg_auto print("✓ Formatage log_mode_change OK") def test_log_mode_change_contextual(): """Test les messages contextuels pour changement de mode""" print("\nTest 8: Messages contextuels log_mode_change...") logger = HumanLogger() # Première fois vers assist - doit inclure l'explication msg1 = logger.log_mode_change("shadow", "assist") assert "Je vais maintenant vous suggérer" in msg1, "L'explication du mode assist doit être présente" assert logger.first_time_events["mode_change"] is True # Deuxième fois - ne doit pas inclure l'explication msg2 = logger.log_mode_change("assist", "auto") assert "Je vais maintenant vous suggérer" not in msg2, "L'explication ne doit pas être répétée" print("✓ Messages contextuels log_mode_change OK") def test_log_mode_change_explanations(): """Test les explications spécifiques à chaque mode""" print("\nTest 9: Explications spécifiques des modes...") # Test mode assist logger_assist = HumanLogger() msg_assist = logger_assist.log_mode_change("shadow", "assist") assert "suggérer des actions" in msg_assist # Test mode copilot logger_copilot = HumanLogger() msg_copilot = logger_copilot.log_mode_change("assist", "copilot") assert "exécuter avec votre validation" in msg_copilot # Test mode auto logger_auto = HumanLogger() msg_auto = logger_auto.log_mode_change("copilot", "auto") assert "agir de manière autonome" in msg_auto # Test mode shadow (pas d'explication spéciale) logger_shadow = HumanLogger() msg_shadow = logger_shadow.log_mode_change("assist", "shadow") assert "💡" not in msg_shadow or "Je vais maintenant" not in msg_shadow print("✓ Explications spécifiques des modes OK") def test_log_finetuning_started_format(): """Test le formatage des messages de début de fine-tuning""" print("\nTest 10: Formatage log_finetuning_started...") logger = HumanLogger() msg = logger.log_finetuning_started(10) assert "🧠" in msg, "L'emoji de cerveau doit être présent" assert "10 exemples" in msg, "Le nombre d'exemples doit être présent" assert "Amélioration du modèle" in msg, "Le message doit contenir 'Amélioration du modèle'" print("✓ Formatage log_finetuning_started OK") def test_log_finetuning_started_contextual(): """Test les messages contextuels pour début de fine-tuning""" print("\nTest 11: Messages contextuels log_finetuning_started...") logger = HumanLogger() # Première fois - doit inclure l'explication msg1 = logger.log_finetuning_started(10) assert "J'améliore ma compréhension" in msg1, "L'explication doit être présente la première fois" assert logger.first_time_events["finetuning_started"] is True # Deuxième fois - ne doit pas inclure l'explication msg2 = logger.log_finetuning_started(15) assert "J'améliore ma compréhension" not in msg2, "L'explication ne doit pas être répétée" print("✓ Messages contextuels log_finetuning_started OK") def test_log_finetuning_completed_format(): """Test le formatage des messages de fin de fine-tuning""" print("\nTest 12: Formatage log_finetuning_completed...") logger = HumanLogger() msg1 = logger.log_finetuning_completed(2.5) assert "✅" in msg1, "L'emoji de succès doit être présent" assert "2.5s" in msg1, "La durée doit être présente avec 1 décimale" assert "Modèle amélioré" in msg1 msg2 = logger.log_finetuning_completed(10.123) assert "10.1s" in msg2, "La durée doit être arrondie à 1 décimale" print("✓ Formatage log_finetuning_completed OK") def test_log_error_types(): """Test les différents types d'erreurs""" print("\nTest 13: Types d'erreurs...") logger = HumanLogger() # Test tous les types d'erreurs error_types = ["connection", "permission", "not_found", "timeout", "whitelist", "unknown"] for error_type in error_types: msg = logger.log_error(error_type) assert "⚠️" in msg, f"L'emoji d'avertissement doit être présent pour {error_type}" # Vérifier les messages spécifiques msg_connection = logger.log_error("connection") assert "Impossible de se connecter" in msg_connection msg_permission = logger.log_error("permission") assert "Permission refusée" in msg_permission msg_not_found = logger.log_error("not_found") assert "Élément introuvable" in msg_not_found msg_timeout = logger.log_error("timeout") assert "Délai d'attente dépassé" in msg_timeout msg_whitelist = logger.log_error("whitelist") assert "Application non autorisée" in msg_whitelist msg_unknown = logger.log_error("unknown_type") assert "Une erreur est survenue" in msg_unknown print("✓ Types d'erreurs OK") def test_log_error_with_context(): """Test les erreurs avec contexte""" print("\nTest 14: Erreurs avec contexte...") logger = HumanLogger() msg = logger.log_error("connection", "Calculator") assert "Calculator" in msg, "Le contexte doit être présent" msg2 = logger.log_error("permission", "Firefox") assert "Firefox" in msg2 print("✓ Erreurs avec contexte OK") def test_log_error_suggestions(): """Test les suggestions correctives pour les erreurs""" print("\nTest 15: Suggestions correctives...") logger = HumanLogger() # Vérifier que chaque type d'erreur a une suggestion msg_connection = logger.log_error("connection") assert "💡" in msg_connection, "Une suggestion doit être présente" assert "Vérifiez que l'application est ouverte" in msg_connection msg_permission = logger.log_error("permission") assert "💡" in msg_permission assert "Vérifiez les permissions" in msg_permission msg_not_found = logger.log_error("not_found") assert "💡" in msg_not_found assert "interface a peut-être changé" in msg_not_found msg_timeout = logger.log_error("timeout") assert "💡" in msg_timeout assert "application est peut-être trop lente" in msg_timeout msg_whitelist = logger.log_error("whitelist") assert "💡" in msg_whitelist assert "Ajoutez l'application à la liste autorisée" in msg_whitelist print("✓ Suggestions correctives OK") def test_log_idle(): """Test le message d'inactivité""" print("\nTest 16: Message d'inactivité...") logger = HumanLogger() msg = logger.log_idle() assert "💤" in msg, "L'emoji de sommeil doit être présent" assert "En attente" in msg, "Le message doit indiquer l'attente" print("✓ Message d'inactivité OK") def test_log_stats_update(): """Test le formatage des statistiques""" print("\nTest 17: Formatage des statistiques...") logger = HumanLogger() # Test avec 1 workflow (singulier) msg1 = logger.log_stats_update(12, 2, 1) assert "📊" in msg1, "L'emoji de statistiques doit être présent" assert "12 actions" in msg1 assert "2 patterns" in msg1 assert "1 workflow" in msg1 assert "workflows" not in msg1, "Doit être au singulier pour 1 workflow" # Test avec plusieurs workflows (pluriel) msg2 = logger.log_stats_update(25, 5, 3) assert "25 actions" in msg2 assert "5 patterns" in msg2 assert "3 workflows" in msg2, "Doit être au pluriel pour plusieurs workflows" # Test avec 0 workflow msg3 = logger.log_stats_update(5, 0, 0) assert "0 workflow" in msg3, "Doit être au singulier pour 0 workflow" print("✓ Formatage des statistiques OK") def test_log_suggestion_ready(): """Test le message de suggestion prête""" print("\nTest 18: Message de suggestion prête...") logger = HumanLogger() msg = logger.log_suggestion_ready("Ouvrir facture") assert "💡" in msg, "L'emoji d'idée doit être présent" assert "Prêt à suggérer" in msg assert "Ouvrir facture" in msg, "Le nom de la tâche doit être présent" print("✓ Message de suggestion prête OK") def test_log_collecting_examples(): """Test le message de collecte d'exemples""" print("\nTest 19: Message de collecte d'exemples...") logger = HumanLogger() msg = logger.log_collecting_examples(8, 10) assert "🧠" in msg, "L'emoji de cerveau doit être présent" assert "8/10" in msg, "La progression doit être présente" assert "Collecte d'exemples" in msg # Test avec différentes valeurs msg2 = logger.log_collecting_examples(1, 5) assert "1/5" in msg2 msg3 = logger.log_collecting_examples(10, 10) assert "10/10" in msg3 print("✓ Message de collecte d'exemples OK") def test_emoji_consistency(): """Test la cohérence des emojis utilisés""" print("\nTest 20: Cohérence des emojis...") logger = HumanLogger() # Vérifier que les mêmes emojis sont utilisés de manière cohérente emojis = { "observation": "👀", "pattern": "🎯", "workflow": "📚", "success": "✅", "brain": "🧠", "warning": "⚠️", "idea": "💡", "stats": "📊", "sleep": "💤" } # Observation assert emojis["observation"] in logger.log_observation("click", "Test") # Pattern assert emojis["pattern"] in logger.log_pattern_detected(3, "Test") # Workflow assert emojis["workflow"] in logger.log_workflow_learned("Test", 5) # Success assert emojis["success"] in logger.log_mode_change("shadow", "assist") assert emojis["success"] in logger.log_finetuning_completed(2.5) # Brain assert emojis["brain"] in logger.log_finetuning_started(10) assert emojis["brain"] in logger.log_collecting_examples(8, 10) # Warning assert emojis["warning"] in logger.log_error("connection") # Idea assert emojis["idea"] in logger.log_suggestion_ready("Test") # Stats assert emojis["stats"] in logger.log_stats_update(12, 2, 1) # Sleep assert emojis["sleep"] in logger.log_idle() print("✓ Cohérence des emojis OK") def test_message_length(): """Test que les messages ne sont pas trop longs""" print("\nTest 21: Longueur des messages...") logger = HumanLogger() # Les messages de base (sans contexte) ne doivent pas dépasser 80 caractères msg1 = logger.log_observation("click", "Calculator") base_msg1 = msg1.split("\n")[0] # Première ligne seulement assert len(base_msg1) <= 80, f"Message trop long: {len(base_msg1)} caractères" # Créer un nouveau logger pour éviter les messages contextuels logger2 = HumanLogger() logger2.first_time_events = {k: True for k in logger2.first_time_events} msg2 = logger2.log_pattern_detected(3, "Calculer 9/9") base_msg2 = msg2.split("\n")[0] assert len(base_msg2) <= 80, f"Message trop long: {len(base_msg2)} caractères" msg3 = logger2.log_workflow_learned("Ouvrir facture", 5) base_msg3 = msg3.split("\n")[0] assert len(base_msg3) <= 80, f"Message trop long: {len(base_msg3)} caractères" print("✓ Longueur des messages OK") def test_first_time_tracking(): """Test le tracking des événements 'première fois'""" print("\nTest 22: Tracking des premières fois...") logger = HumanLogger() # Vérifier l'état initial assert all(not v for v in logger.first_time_events.values()), "Tous les flags doivent être False au départ" # Déclencher chaque événement et vérifier le flag logger.log_pattern_detected(3, "Test") assert logger.first_time_events["pattern_detected"] is True logger.log_workflow_learned("Test", 5) assert logger.first_time_events["workflow_detected"] is True logger.log_mode_change("shadow", "assist") assert logger.first_time_events["mode_change"] is True logger.log_finetuning_started(10) assert logger.first_time_events["finetuning_started"] is True print("✓ Tracking des premières fois OK") def run_all_tests(): """Exécute tous les tests""" print("=" * 60) print("Tests unitaires de HumanLogger") print("=" * 60) try: test_initialization() test_log_observation_format() test_log_pattern_detected_emoji() test_log_pattern_detected_contextual() test_log_workflow_learned_format() test_log_workflow_learned_contextual() test_log_mode_change_format() test_log_mode_change_contextual() test_log_mode_change_explanations() test_log_finetuning_started_format() test_log_finetuning_started_contextual() test_log_finetuning_completed_format() test_log_error_types() test_log_error_with_context() test_log_error_suggestions() test_log_idle() test_log_stats_update() test_log_suggestion_ready() test_log_collecting_examples() test_emoji_consistency() test_message_length() test_first_time_tracking() print("\n" + "=" * 60) print("✓ TOUS LES TESTS RÉUSSIS!") print("=" * 60) return True except AssertionError as e: print(f"\n✗ ÉCHEC DU TEST: {e}") import traceback traceback.print_exc() return False except Exception as e: print(f"\n✗ ERREUR: {e}") import traceback traceback.print_exc() return False if __name__ == "__main__": success = run_all_tests() sys.exit(0 if success else 1)