Files
Geniusia_v2/geniusia2/tests/test_human_logger.py
2026-03-05 00:20:25 +01:00

529 lines
19 KiB
Python

"""
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)