529 lines
19 KiB
Python
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)
|