v1.0 - Version stable: multi-PC, détection UI-DETR-1, 3 modes exécution
- Frontend v4 accessible sur réseau local (192.168.1.40) - Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard) - Ollama GPU fonctionnel - Self-healing interactif - Dashboard confiance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
106
tests/unit/test_terrain_text_normalization.py
Normal file
106
tests/unit/test_terrain_text_normalization.py
Normal file
@@ -0,0 +1,106 @@
|
||||
"""
|
||||
Tests pour Fiche #8 - Anti-bugs terrain : Normalisation texte
|
||||
|
||||
Auteur: Dom, Alice Kiro - 15 décembre 2024
|
||||
Objectif: Valider la normalisation de texte pour OCR capricieux et variations
|
||||
|
||||
Tests:
|
||||
1. Normalisation accents/casse/espaces
|
||||
2. Fuzzy matching OCR
|
||||
3. Gestion NBSP et caractères spéciaux
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
# Marquer tous les tests de ce fichier comme fiche8
|
||||
pytestmark = pytest.mark.fiche8
|
||||
|
||||
from datetime import datetime
|
||||
from core.execution.target_resolver import TargetResolver, ResolutionContext, _norm_text, _fuzzy_ratio
|
||||
from core.models.workflow_graph import TargetSpec
|
||||
from core.models.screen_state import ScreenState, RawLevel, PerceptionLevel, ContextLevel, WindowContext, EmbeddingRef
|
||||
from core.models.ui_element import UIElement, UIElementEmbeddings, VisualFeatures
|
||||
|
||||
|
||||
def E(eid, role, bbox, label="", etype="ui", conf=0.9):
|
||||
"""Helper pour créer un UIElement rapidement"""
|
||||
return UIElement(
|
||||
element_id=eid,
|
||||
type=etype,
|
||||
role=role,
|
||||
bbox=bbox,
|
||||
center=(bbox[0] + bbox[2]//2, bbox[1] + bbox[3]//2),
|
||||
label=label,
|
||||
label_confidence=1.0,
|
||||
embeddings=UIElementEmbeddings(image=None, text=None),
|
||||
visual_features=VisualFeatures(dominant_color="n/a", has_icon=False, shape="rectangle", size_category="medium"),
|
||||
confidence=conf,
|
||||
tags=[],
|
||||
metadata={}
|
||||
)
|
||||
|
||||
|
||||
def S(elements):
|
||||
"""Helper pour créer un ScreenState rapidement"""
|
||||
return ScreenState(
|
||||
screen_state_id="s",
|
||||
timestamp=datetime.now(),
|
||||
session_id="sess",
|
||||
window=WindowContext(app_name="app", window_title="win", screen_resolution=[1920,1080]),
|
||||
raw=RawLevel(screenshot_path="x", capture_method="test", file_size_bytes=1),
|
||||
perception=PerceptionLevel(
|
||||
embedding=EmbeddingRef(provider="p", vector_id="v", dimensions=1),
|
||||
detected_text=[],
|
||||
text_detection_method="none",
|
||||
confidence_avg=0.0
|
||||
),
|
||||
context=ContextLevel(),
|
||||
ui_elements=elements
|
||||
)
|
||||
|
||||
|
||||
def test_text_normalization_accents_case_spaces():
|
||||
"""Test normalisation accents/casse/espaces avec NBSP"""
|
||||
# Label avec NBSP + majuscules + accents
|
||||
btn = E("btn", "button", (100, 100, 120, 30), "Se\u00A0Connecter", etype="button")
|
||||
screen = S([btn])
|
||||
|
||||
spec = TargetSpec(by_text="se connecter") # minuscules, espace normal
|
||||
r = TargetResolver()
|
||||
res = r.resolve_target(spec, screen, ResolutionContext(screen_state=screen, previous_target=None))
|
||||
|
||||
assert res is not None
|
||||
assert res.element.element_id == "btn"
|
||||
|
||||
|
||||
def test_fuzzy_matching_ocr_errors():
|
||||
"""Test fuzzy matching pour erreurs OCR typiques"""
|
||||
# OCR a lu "S1gn-in" au lieu de "Sign in"
|
||||
btn1 = E("btn1", "label", (100, 100, 120, 30), "S1gn-in", etype="label") # Changé en label
|
||||
# Autre bouton avec texte différent
|
||||
btn2 = E("btn2", "label", (250, 100, 120, 30), "Cancel", etype="label")
|
||||
screen = S([btn1, btn2])
|
||||
|
||||
spec = TargetSpec(by_text="Sign in") # Seulement by_text
|
||||
r = TargetResolver()
|
||||
res = r.resolve_target(spec, screen, ResolutionContext(screen_state=screen, previous_target=None))
|
||||
|
||||
assert res is not None
|
||||
assert res.element.element_id == "btn1" # Doit matcher malgré l'erreur OCR
|
||||
|
||||
|
||||
def test_normalization_functions_directly():
|
||||
"""Test direct des fonctions de normalisation"""
|
||||
# Test _norm_text
|
||||
assert _norm_text("Se\u00A0Connecter") == "se connecter"
|
||||
assert _norm_text("Café—Bar") == "cafe-bar"
|
||||
assert _norm_text(" Multiple Spaces ") == "multiple spaces"
|
||||
|
||||
# Test _fuzzy_ratio
|
||||
assert _fuzzy_ratio("Sign in", "S1gn-in") > 0.70 # Doit dépasser un seuil raisonnable
|
||||
assert _fuzzy_ratio("Sign in", "Sign-in") > 0.85 # Très proche
|
||||
assert _fuzzy_ratio("Sign in", "Cancel") < 0.50 # Très différent
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
Reference in New Issue
Block a user