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:
298
tests/unit/test_ui_element.py
Normal file
298
tests/unit/test_ui_element.py
Normal file
@@ -0,0 +1,298 @@
|
||||
"""
|
||||
Tests unitaires pour UIElement
|
||||
|
||||
Property 3: UIElement Detection Confidence Bounds
|
||||
Validates: Requirements 3.6
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Ajouter le répertoire racine au path pour les imports
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent))
|
||||
|
||||
from core.models.ui_element import (
|
||||
UIElement,
|
||||
UIElementEmbeddings,
|
||||
VisualFeatures,
|
||||
UI_ELEMENT_TYPES,
|
||||
UI_ELEMENT_ROLES
|
||||
)
|
||||
|
||||
|
||||
class TestUIElementEmbeddings:
|
||||
"""Tests pour UIElementEmbeddings"""
|
||||
|
||||
def test_create_embeddings(self):
|
||||
"""Test création UIElementEmbeddings"""
|
||||
embeddings = UIElementEmbeddings(
|
||||
image={"provider": "openclip", "vector_id": "test_img.npy", "dimensions": 512},
|
||||
text={"provider": "openclip", "vector_id": "test_txt.npy", "dimensions": 512}
|
||||
)
|
||||
|
||||
assert embeddings.image is not None
|
||||
assert embeddings.text is not None
|
||||
|
||||
def test_embeddings_serialization(self):
|
||||
"""Test sérialisation/désérialisation UIElementEmbeddings"""
|
||||
embeddings = UIElementEmbeddings(
|
||||
image={"provider": "openclip", "vector_id": "test.npy", "dimensions": 512}
|
||||
)
|
||||
|
||||
data = embeddings.to_dict()
|
||||
embeddings2 = UIElementEmbeddings.from_dict(data)
|
||||
|
||||
assert embeddings2.image == embeddings.image
|
||||
|
||||
|
||||
class TestVisualFeatures:
|
||||
"""Tests pour VisualFeatures"""
|
||||
|
||||
def test_create_visual_features(self):
|
||||
"""Test création VisualFeatures"""
|
||||
features = VisualFeatures(
|
||||
dominant_color="#4CAF50",
|
||||
has_icon=False,
|
||||
shape="rectangle",
|
||||
size_category="medium"
|
||||
)
|
||||
|
||||
assert features.dominant_color == "#4CAF50"
|
||||
assert features.has_icon is False
|
||||
assert features.shape == "rectangle"
|
||||
|
||||
def test_visual_features_serialization(self):
|
||||
"""Test sérialisation/désérialisation VisualFeatures"""
|
||||
features = VisualFeatures(
|
||||
dominant_color="#4CAF50",
|
||||
has_icon=True,
|
||||
shape="rounded_rectangle",
|
||||
size_category="large"
|
||||
)
|
||||
|
||||
data = features.to_dict()
|
||||
features2 = VisualFeatures.from_dict(data)
|
||||
|
||||
assert features2.dominant_color == features.dominant_color
|
||||
assert features2.has_icon == features.has_icon
|
||||
assert features2.shape == features.shape
|
||||
assert features2.size_category == features.size_category
|
||||
|
||||
|
||||
class TestUIElement:
|
||||
"""Tests pour UIElement"""
|
||||
|
||||
def create_test_ui_element(self, confidence: float = 0.94) -> UIElement:
|
||||
"""Helper pour créer un UIElement de test"""
|
||||
embeddings = UIElementEmbeddings(
|
||||
image={"provider": "openclip", "vector_id": "test_img.npy", "dimensions": 512},
|
||||
text={"provider": "openclip", "vector_id": "test_txt.npy", "dimensions": 512}
|
||||
)
|
||||
|
||||
visual_features = VisualFeatures(
|
||||
dominant_color="#4CAF50",
|
||||
has_icon=False,
|
||||
shape="rectangle",
|
||||
size_category="medium"
|
||||
)
|
||||
|
||||
return UIElement(
|
||||
element_id="el_btn_001",
|
||||
type="button",
|
||||
role="primary_action",
|
||||
bbox=(100, 200, 150, 40),
|
||||
center=(175, 220),
|
||||
label="Submit",
|
||||
label_confidence=0.96,
|
||||
embeddings=embeddings,
|
||||
visual_features=visual_features,
|
||||
tags=["action", "primary"],
|
||||
confidence=confidence
|
||||
)
|
||||
|
||||
def test_create_ui_element(self):
|
||||
"""Test création UIElement"""
|
||||
element = self.create_test_ui_element()
|
||||
|
||||
assert element.element_id == "el_btn_001"
|
||||
assert element.type == "button"
|
||||
assert element.role == "primary_action"
|
||||
assert element.label == "Submit"
|
||||
assert element.confidence == 0.94
|
||||
|
||||
def test_ui_element_bbox(self):
|
||||
"""Test bbox et center"""
|
||||
element = self.create_test_ui_element()
|
||||
|
||||
assert element.bbox == (100, 200, 150, 40)
|
||||
assert element.center == (175, 220)
|
||||
|
||||
def test_ui_element_confidence_validation(self):
|
||||
"""
|
||||
Property 3: UIElement Detection Confidence Bounds
|
||||
|
||||
Pour tout UIElement, le score de confiance doit être entre 0.0 et 1.0
|
||||
|
||||
Validates: Requirements 3.6
|
||||
"""
|
||||
# Confidence valide
|
||||
element = self.create_test_ui_element(confidence=0.94)
|
||||
assert 0.0 <= element.confidence <= 1.0
|
||||
|
||||
# Confidence à 0
|
||||
element = self.create_test_ui_element(confidence=0.0)
|
||||
assert element.confidence == 0.0
|
||||
|
||||
# Confidence à 1
|
||||
element = self.create_test_ui_element(confidence=1.0)
|
||||
assert element.confidence == 1.0
|
||||
|
||||
# Confidence invalide (> 1)
|
||||
with pytest.raises(ValueError, match="Confidence must be between 0 and 1"):
|
||||
self.create_test_ui_element(confidence=1.5)
|
||||
|
||||
# Confidence invalide (< 0)
|
||||
with pytest.raises(ValueError, match="Confidence must be between 0 and 1"):
|
||||
self.create_test_ui_element(confidence=-0.1)
|
||||
|
||||
def test_ui_element_to_dict(self):
|
||||
"""Test sérialisation to_dict"""
|
||||
element = self.create_test_ui_element()
|
||||
|
||||
data = element.to_dict()
|
||||
|
||||
assert data["element_id"] == "el_btn_001"
|
||||
assert data["type"] == "button"
|
||||
assert data["role"] == "primary_action"
|
||||
assert data["label"] == "Submit"
|
||||
assert data["confidence"] == 0.94
|
||||
assert "embeddings" in data
|
||||
assert "visual_features" in data
|
||||
|
||||
def test_ui_element_from_dict(self):
|
||||
"""Test désérialisation from_dict"""
|
||||
element = self.create_test_ui_element()
|
||||
|
||||
data = element.to_dict()
|
||||
element2 = UIElement.from_dict(data)
|
||||
|
||||
assert element2.element_id == element.element_id
|
||||
assert element2.type == element.type
|
||||
assert element2.role == element.role
|
||||
assert element2.bbox == element.bbox
|
||||
assert element2.confidence == element.confidence
|
||||
|
||||
def test_ui_element_round_trip(self):
|
||||
"""Test round trip sérialisation/désérialisation"""
|
||||
element = self.create_test_ui_element()
|
||||
|
||||
data = element.to_dict()
|
||||
element2 = UIElement.from_dict(data)
|
||||
|
||||
# Vérifier tous les champs
|
||||
assert element2.element_id == element.element_id
|
||||
assert element2.type == element.type
|
||||
assert element2.role == element.role
|
||||
assert element2.bbox == element.bbox
|
||||
assert element2.center == element.center
|
||||
assert element2.label == element.label
|
||||
assert element2.label_confidence == element.label_confidence
|
||||
assert element2.confidence == element.confidence
|
||||
assert element2.tags == element.tags
|
||||
|
||||
# Vérifier embeddings
|
||||
assert element2.embeddings.image == element.embeddings.image
|
||||
assert element2.embeddings.text == element.embeddings.text
|
||||
|
||||
# Vérifier visual features
|
||||
assert element2.visual_features.dominant_color == element.visual_features.dominant_color
|
||||
assert element2.visual_features.has_icon == element.visual_features.has_icon
|
||||
|
||||
def test_ui_element_to_json_string(self):
|
||||
"""Test sérialisation to_json (string)"""
|
||||
element = self.create_test_ui_element()
|
||||
|
||||
json_str = element.to_json()
|
||||
assert isinstance(json_str, str)
|
||||
|
||||
# Vérifier que c'est du JSON valide
|
||||
data = json.loads(json_str)
|
||||
assert data["element_id"] == "el_btn_001"
|
||||
|
||||
def test_ui_element_from_json_string(self):
|
||||
"""Test désérialisation from_json (string)"""
|
||||
element = self.create_test_ui_element()
|
||||
|
||||
json_str = element.to_json()
|
||||
element2 = UIElement.from_json(json_str)
|
||||
|
||||
assert element2.element_id == element.element_id
|
||||
assert element2.confidence == element.confidence
|
||||
|
||||
def test_ui_element_with_metadata(self):
|
||||
"""Test UIElement avec métadonnées"""
|
||||
element = self.create_test_ui_element()
|
||||
element.metadata = {"detection_method": "qwen_vl", "detection_time_ms": 45}
|
||||
|
||||
data = element.to_dict()
|
||||
element2 = UIElement.from_dict(data)
|
||||
|
||||
assert element2.metadata["detection_method"] == "qwen_vl"
|
||||
assert element2.metadata["detection_time_ms"] == 45
|
||||
|
||||
def test_ui_element_types_defined(self):
|
||||
"""Test que les types UI sont définis"""
|
||||
assert "button" in UI_ELEMENT_TYPES
|
||||
assert "text_input" in UI_ELEMENT_TYPES
|
||||
assert "checkbox" in UI_ELEMENT_TYPES
|
||||
assert len(UI_ELEMENT_TYPES) > 0
|
||||
|
||||
def test_ui_element_roles_defined(self):
|
||||
"""Test que les rôles UI sont définis"""
|
||||
assert "primary_action" in UI_ELEMENT_ROLES
|
||||
assert "cancel" in UI_ELEMENT_ROLES
|
||||
assert "form_input" in UI_ELEMENT_ROLES
|
||||
assert len(UI_ELEMENT_ROLES) > 0
|
||||
|
||||
def test_ui_element_different_types(self):
|
||||
"""Test création d'éléments de différents types"""
|
||||
embeddings = UIElementEmbeddings()
|
||||
visual_features = VisualFeatures(
|
||||
dominant_color="#FFFFFF",
|
||||
has_icon=False,
|
||||
shape="rectangle",
|
||||
size_category="small"
|
||||
)
|
||||
|
||||
# Button
|
||||
button = UIElement(
|
||||
element_id="el_001",
|
||||
type="button",
|
||||
role="primary_action",
|
||||
bbox=(0, 0, 100, 30),
|
||||
center=(50, 15),
|
||||
label="Click",
|
||||
label_confidence=0.9,
|
||||
embeddings=embeddings,
|
||||
visual_features=visual_features,
|
||||
confidence=0.9
|
||||
)
|
||||
assert button.type == "button"
|
||||
|
||||
# Text input
|
||||
text_input = UIElement(
|
||||
element_id="el_002",
|
||||
type="text_input",
|
||||
role="form_input",
|
||||
bbox=(0, 0, 200, 30),
|
||||
center=(100, 15),
|
||||
label="Name",
|
||||
label_confidence=0.85,
|
||||
embeddings=embeddings,
|
||||
visual_features=visual_features,
|
||||
confidence=0.85
|
||||
)
|
||||
assert text_input.type == "text_input"
|
||||
assert text_input.role == "form_input"
|
||||
Reference in New Issue
Block a user