372 lines
11 KiB
Python
372 lines
11 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Test du WorkflowMatcher - Vérifie la correspondance entre actions et workflows
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
sys.path.insert(0, str(Path(__file__).parent / "geniusia2"))
|
|
|
|
from core.logger import Logger
|
|
from core.config import get_config
|
|
from core.workflow_matcher import WorkflowMatcher, WorkflowMatch
|
|
|
|
|
|
def test_perfect_match():
|
|
"""Test avec un match parfait"""
|
|
print("\n" + "="*60)
|
|
print("🧪 TEST 1: Match parfait")
|
|
print("="*60)
|
|
|
|
logger = Logger()
|
|
config = get_config()
|
|
|
|
matcher = WorkflowMatcher(logger, config)
|
|
|
|
# Actions courantes (2 premières étapes d'un workflow)
|
|
session_actions = [
|
|
{
|
|
"action_type": "click",
|
|
"position": [100, 100],
|
|
"window": "Calculatrice"
|
|
},
|
|
{
|
|
"action_type": "type",
|
|
"position": [150, 150],
|
|
"window": "Calculatrice"
|
|
}
|
|
]
|
|
|
|
# Workflow connu (3 étapes)
|
|
workflow = {
|
|
"workflow_id": "calc_001",
|
|
"name": "Calcul simple",
|
|
"steps": [
|
|
{
|
|
"action_type": "click",
|
|
"position": [100, 100],
|
|
"window": "Calculatrice"
|
|
},
|
|
{
|
|
"action_type": "type",
|
|
"position": [150, 150],
|
|
"window": "Calculatrice"
|
|
},
|
|
{
|
|
"action_type": "click",
|
|
"position": [200, 200],
|
|
"window": "Calculatrice"
|
|
}
|
|
]
|
|
}
|
|
|
|
# Matcher
|
|
matches = matcher.match_current_session(session_actions, [workflow])
|
|
|
|
print(f"\n📊 Résultats:")
|
|
print(f" Matches trouvés: {len(matches)}")
|
|
|
|
if matches:
|
|
match = matches[0]
|
|
print(f" Workflow: {match.workflow_name}")
|
|
print(f" Confiance: {match.confidence:.2%}")
|
|
print(f" Étapes matchées: {match.matched_steps}/{match.total_steps}")
|
|
print(f" Étapes restantes: {len(match.remaining_steps)}")
|
|
|
|
assert match.confidence >= 0.8, f"Confiance trop faible: {match.confidence}"
|
|
assert match.matched_steps == 2, f"Devrait matcher 2 étapes, trouvé {match.matched_steps}"
|
|
assert len(match.remaining_steps) == 1, f"Devrait rester 1 étape, trouvé {len(match.remaining_steps)}"
|
|
|
|
print(f"\n✅ Match parfait détecté !")
|
|
return True
|
|
else:
|
|
print(f"\n❌ Aucun match trouvé")
|
|
return False
|
|
|
|
|
|
def test_position_tolerance():
|
|
"""Test avec tolérance de position"""
|
|
print("\n" + "="*60)
|
|
print("🧪 TEST 2: Tolérance de position")
|
|
print("="*60)
|
|
|
|
logger = Logger()
|
|
config = get_config()
|
|
|
|
matcher = WorkflowMatcher(logger, config)
|
|
|
|
# Actions avec positions légèrement décalées
|
|
session_actions = [
|
|
{
|
|
"action_type": "click",
|
|
"position": [120, 110], # Décalé de 20px
|
|
"window": "Firefox"
|
|
},
|
|
{
|
|
"action_type": "type",
|
|
"position": [165, 155], # Décalé de 15px
|
|
"window": "Firefox"
|
|
}
|
|
]
|
|
|
|
# Workflow avec positions originales
|
|
workflow = {
|
|
"workflow_id": "firefox_001",
|
|
"name": "Recherche Firefox",
|
|
"steps": [
|
|
{
|
|
"action_type": "click",
|
|
"position": [100, 100],
|
|
"window": "Firefox"
|
|
},
|
|
{
|
|
"action_type": "type",
|
|
"position": [150, 150],
|
|
"window": "Firefox"
|
|
},
|
|
{
|
|
"action_type": "click",
|
|
"position": [300, 200],
|
|
"window": "Firefox"
|
|
}
|
|
]
|
|
}
|
|
|
|
matches = matcher.match_current_session(session_actions, [workflow])
|
|
|
|
print(f"\n📊 Résultats:")
|
|
print(f" Matches trouvés: {len(matches)}")
|
|
|
|
if matches:
|
|
match = matches[0]
|
|
print(f" Workflow: {match.workflow_name}")
|
|
print(f" Confiance: {match.confidence:.2%}")
|
|
print(f" Étapes matchées: {match.matched_steps}/{match.total_steps}")
|
|
|
|
# Avec tolérance de 50px, devrait matcher
|
|
assert match.confidence >= 0.7, f"Confiance trop faible avec tolérance: {match.confidence}"
|
|
|
|
print(f"\n✅ Tolérance de position fonctionne !")
|
|
return True
|
|
else:
|
|
print(f"\n❌ Aucun match trouvé (tolérance insuffisante ?)")
|
|
return False
|
|
|
|
|
|
def test_best_match_selection():
|
|
"""Test de sélection du meilleur match"""
|
|
print("\n" + "="*60)
|
|
print("🧪 TEST 3: Sélection du meilleur match")
|
|
print("="*60)
|
|
|
|
logger = Logger()
|
|
config = get_config()
|
|
|
|
matcher = WorkflowMatcher(logger, config)
|
|
|
|
# Actions courantes
|
|
session_actions = [
|
|
{
|
|
"action_type": "click",
|
|
"position": [100, 100],
|
|
"window": "OnlyOffice"
|
|
},
|
|
{
|
|
"action_type": "type",
|
|
"position": [150, 150],
|
|
"window": "OnlyOffice"
|
|
}
|
|
]
|
|
|
|
# Plusieurs workflows possibles
|
|
workflows = [
|
|
{
|
|
"workflow_id": "office_001",
|
|
"name": "Workflow A (bon match)",
|
|
"steps": [
|
|
{
|
|
"action_type": "click",
|
|
"position": [100, 100],
|
|
"window": "OnlyOffice"
|
|
},
|
|
{
|
|
"action_type": "type",
|
|
"position": [150, 150],
|
|
"window": "OnlyOffice"
|
|
},
|
|
{
|
|
"action_type": "click",
|
|
"position": [200, 200],
|
|
"window": "OnlyOffice"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"workflow_id": "office_002",
|
|
"name": "Workflow B (mauvais match)",
|
|
"steps": [
|
|
{
|
|
"action_type": "scroll", # Type différent
|
|
"position": [100, 100],
|
|
"window": "OnlyOffice"
|
|
},
|
|
{
|
|
"action_type": "click",
|
|
"position": [150, 150],
|
|
"window": "OnlyOffice"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
|
|
matches = matcher.match_current_session(session_actions, workflows)
|
|
|
|
print(f"\n📊 Résultats:")
|
|
print(f" Matches trouvés: {len(matches)}")
|
|
|
|
for i, match in enumerate(matches):
|
|
print(f"\n Match {i+1}:")
|
|
print(f" Workflow: {match.workflow_name}")
|
|
print(f" Confiance: {match.confidence:.2%}")
|
|
|
|
# Trouver le meilleur
|
|
best = matcher.find_best_match(matches)
|
|
|
|
if best:
|
|
print(f"\n🏆 Meilleur match:")
|
|
print(f" Workflow: {best.workflow_name}")
|
|
print(f" Confiance: {best.confidence:.2%}")
|
|
|
|
# Le meilleur devrait être le Workflow A
|
|
assert best.workflow_id == "office_001", f"Mauvais workflow sélectionné: {best.workflow_id}"
|
|
assert best.confidence >= 0.8, f"Confiance insuffisante: {best.confidence}"
|
|
|
|
# Vérifier les détails
|
|
details = matcher.get_match_details(best)
|
|
print(f"\n📋 Détails:")
|
|
print(f" Étapes matchées: {details['matched_steps']}/{details['total_steps']}")
|
|
print(f" Complétion: {details['completion_percentage']:.1f}%")
|
|
print(f" Prochaines étapes: {len(details['next_steps_preview'])}")
|
|
|
|
print(f"\n✅ Meilleur match correctement sélectionné !")
|
|
return True
|
|
else:
|
|
print(f"\n❌ Aucun match au-dessus du seuil")
|
|
return False
|
|
|
|
|
|
def test_no_match():
|
|
"""Test sans correspondance"""
|
|
print("\n" + "="*60)
|
|
print("🧪 TEST 4: Aucune correspondance")
|
|
print("="*60)
|
|
|
|
logger = Logger()
|
|
config = get_config()
|
|
|
|
matcher = WorkflowMatcher(logger, config)
|
|
|
|
# Actions complètement différentes
|
|
session_actions = [
|
|
{
|
|
"action_type": "scroll",
|
|
"position": [500, 500],
|
|
"window": "Terminal"
|
|
}
|
|
]
|
|
|
|
# Workflow différent
|
|
workflow = {
|
|
"workflow_id": "calc_001",
|
|
"name": "Calcul",
|
|
"steps": [
|
|
{
|
|
"action_type": "click",
|
|
"position": [100, 100],
|
|
"window": "Calculatrice"
|
|
}
|
|
]
|
|
}
|
|
|
|
matches = matcher.match_current_session(session_actions, [workflow])
|
|
best = matcher.find_best_match(matches)
|
|
|
|
print(f"\n📊 Résultats:")
|
|
print(f" Matches trouvés: {len(matches)}")
|
|
print(f" Meilleur match: {best}")
|
|
|
|
# Ne devrait pas trouver de match au-dessus du seuil
|
|
assert best is None, "Ne devrait pas trouver de match"
|
|
|
|
print(f"\n✅ Aucun faux positif !")
|
|
return True
|
|
|
|
|
|
def main():
|
|
"""Exécute tous les tests"""
|
|
print("\n" + "="*60)
|
|
print("🚀 TEST DU WORKFLOW MATCHER")
|
|
print("="*60)
|
|
|
|
results = []
|
|
|
|
try:
|
|
results.append(("Match parfait", test_perfect_match()))
|
|
except Exception as e:
|
|
print(f"\n❌ ERREUR Test 1: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
results.append(("Match parfait", False))
|
|
|
|
try:
|
|
results.append(("Tolérance position", test_position_tolerance()))
|
|
except Exception as e:
|
|
print(f"\n❌ ERREUR Test 2: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
results.append(("Tolérance position", False))
|
|
|
|
try:
|
|
results.append(("Meilleur match", test_best_match_selection()))
|
|
except Exception as e:
|
|
print(f"\n❌ ERREUR Test 3: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
results.append(("Meilleur match", False))
|
|
|
|
try:
|
|
results.append(("Aucune correspondance", test_no_match()))
|
|
except Exception as e:
|
|
print(f"\n❌ ERREUR Test 4: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
results.append(("Aucune correspondance", False))
|
|
|
|
# Résumé
|
|
print("\n" + "="*60)
|
|
print("📊 RÉSUMÉ DES TESTS")
|
|
print("="*60)
|
|
|
|
for name, success in results:
|
|
status = "✅" if success else "❌"
|
|
print(f"{status} {name}")
|
|
|
|
total = len(results)
|
|
passed = sum(1 for _, success in results if success)
|
|
|
|
print(f"\n📈 Score: {passed}/{total} tests réussis")
|
|
|
|
if passed == total:
|
|
print("\n🎉 TOUS LES TESTS SONT PASSÉS !")
|
|
print("\n💡 Prochaine étape:")
|
|
print(" Intégrer WorkflowMatcher dans SuggestionManager")
|
|
return 0
|
|
else:
|
|
print(f"\n⚠️ {total - passed} test(s) échoué(s)")
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|