Initial commit
This commit is contained in:
379
test_ui_element_phase1.py
Normal file
379
test_ui_element_phase1.py
Normal file
@@ -0,0 +1,379 @@
|
||||
"""
|
||||
Tests d'intégration pour Phase 1 - Mode Light des structures UI Element.
|
||||
Vérifie que toutes les structures de données fonctionnent correctement ensemble.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
# Ajouter le chemin du module
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
|
||||
from geniusia2.core import (
|
||||
UIElement,
|
||||
UIElementType,
|
||||
VisualData,
|
||||
TextData,
|
||||
ElementProperties,
|
||||
ElementContext,
|
||||
EnrichedScreenState,
|
||||
WindowInfo,
|
||||
RawData,
|
||||
PerceptionData,
|
||||
StateEmbedding,
|
||||
ContextData,
|
||||
ScreenStateManager
|
||||
)
|
||||
from geniusia2.core.logger import Logger
|
||||
from geniusia2.core.workflow_state_adapter import WorkflowStateAdapter
|
||||
from geniusia2.core.workflow_detector import WorkflowStep
|
||||
|
||||
|
||||
def test_uielement_creation():
|
||||
"""Test création et sérialisation d'UIElement."""
|
||||
print("\n" + "=" * 70)
|
||||
print("TEST 1: Création et sérialisation d'UIElement")
|
||||
print("=" * 70)
|
||||
|
||||
# Créer un UIElement
|
||||
element_id = UIElement.generate_element_id(
|
||||
app_name="test_app",
|
||||
bbox=(100, 200, 300, 250),
|
||||
label="Valider"
|
||||
)
|
||||
|
||||
element = UIElement(
|
||||
element_id=element_id,
|
||||
type=UIElementType.BUTTON,
|
||||
role="validate_action",
|
||||
bbox=(100, 200, 300, 250),
|
||||
label="Valider",
|
||||
visual=VisualData(
|
||||
screenshot_path="data/elements/el_001.png",
|
||||
embedding_provider="openclip_ViT-B-32",
|
||||
embedding_vector_id="data/embeddings/el_001.npy"
|
||||
),
|
||||
text=TextData(
|
||||
raw="Valider",
|
||||
normalized="valider",
|
||||
embedding_provider="clip_text",
|
||||
embedding_vector_id="data/embeddings/el_001_text.npy"
|
||||
),
|
||||
properties=ElementProperties(
|
||||
is_clickable=True,
|
||||
is_focusable=True,
|
||||
is_dangerous=False
|
||||
),
|
||||
context=ElementContext(
|
||||
app_name="test_app",
|
||||
window_title="Test Window",
|
||||
workflow_hint="WF_test"
|
||||
),
|
||||
tags=["primary_action"],
|
||||
confidence=0.95,
|
||||
detection_method="heuristic_rectangle"
|
||||
)
|
||||
|
||||
print(f"✓ UIElement créé: {element.element_id}")
|
||||
print(f" Type: {element.type.value}")
|
||||
print(f" Label: {element.label}")
|
||||
print(f" Confidence: {element.confidence}")
|
||||
|
||||
# Test sérialisation
|
||||
json_str = element.to_json()
|
||||
element_restored = UIElement.from_json(json_str)
|
||||
|
||||
assert element_restored.element_id == element.element_id
|
||||
assert element_restored.type == element.type
|
||||
assert element_restored.label == element.label
|
||||
print(f"✓ Sérialisation/désérialisation réussie")
|
||||
|
||||
# Test stabilité de l'ID
|
||||
element_id_2 = UIElement.generate_element_id(
|
||||
app_name="test_app",
|
||||
bbox=(100, 200, 300, 250),
|
||||
label="Valider"
|
||||
)
|
||||
assert element_id == element_id_2
|
||||
print(f"✓ Stabilité de l'element_id vérifiée")
|
||||
|
||||
return element
|
||||
|
||||
|
||||
def test_enriched_screen_state_light_mode():
|
||||
"""Test création d'EnrichedScreenState en mode light."""
|
||||
print("\n" + "=" * 70)
|
||||
print("TEST 2: EnrichedScreenState en mode light")
|
||||
print("=" * 70)
|
||||
|
||||
window = WindowInfo(
|
||||
app_name="test_app",
|
||||
window_title="Test Window",
|
||||
screen_resolution=(1920, 1080)
|
||||
)
|
||||
|
||||
screen_state = EnrichedScreenState.create_light_mode(
|
||||
screen_state_id="screen_test_001",
|
||||
session_id="session_001",
|
||||
window=window,
|
||||
screenshot_path="data/screens/screen_001.png",
|
||||
image_embedding_provider="openclip_ViT-B-32",
|
||||
image_embedding_vector_id="data/embeddings/screen_001.npy"
|
||||
)
|
||||
|
||||
print(f"✓ EnrichedScreenState créé: {screen_state.screen_state_id}")
|
||||
print(f" Mode: {screen_state.mode}")
|
||||
print(f" UI Elements: {len(screen_state.ui_elements)}")
|
||||
print(f" State Embedding Provider: {screen_state.state_embedding.provider}")
|
||||
|
||||
# Vérifier les propriétés du mode light
|
||||
assert screen_state.mode == "light"
|
||||
assert len(screen_state.ui_elements) == 0
|
||||
assert screen_state.state_embedding.components is None
|
||||
print(f"✓ Mode light vérifié (ui_elements vide, pas de composantes)")
|
||||
|
||||
# Test sérialisation
|
||||
json_str = screen_state.to_json()
|
||||
screen_state_restored = EnrichedScreenState.from_json(json_str)
|
||||
|
||||
assert screen_state_restored.screen_state_id == screen_state.screen_state_id
|
||||
assert screen_state_restored.mode == screen_state.mode
|
||||
print(f"✓ Sérialisation/désérialisation réussie")
|
||||
|
||||
return screen_state
|
||||
|
||||
|
||||
def test_screen_state_manager():
|
||||
"""Test du ScreenStateManager."""
|
||||
print("\n" + "=" * 70)
|
||||
print("TEST 3: ScreenStateManager")
|
||||
print("=" * 70)
|
||||
|
||||
logger = Logger(log_dir="test_logs")
|
||||
manager = ScreenStateManager(
|
||||
logger=logger,
|
||||
data_dir="test_data",
|
||||
mode="light"
|
||||
)
|
||||
|
||||
print(f"✓ ScreenStateManager initialisé en mode: {manager.mode}")
|
||||
|
||||
# Créer un screen state
|
||||
screen_state = manager.create_screen_state(
|
||||
session_id="test_session_001",
|
||||
window_title="Test Window",
|
||||
app_name="test_app",
|
||||
screenshot_path="test_data/screens/test_001.png",
|
||||
screen_resolution=(1920, 1080),
|
||||
detected_text=["Test", "Button"],
|
||||
context_tags=["test"]
|
||||
)
|
||||
|
||||
print(f"✓ Screen state créé: {screen_state.screen_state_id}")
|
||||
|
||||
# Sauvegarder avec embedding
|
||||
test_embedding = np.random.rand(512)
|
||||
state_file = manager.save_screen_state(
|
||||
screen_state,
|
||||
save_embedding=True,
|
||||
embedding_vector=test_embedding
|
||||
)
|
||||
|
||||
print(f"✓ Screen state sauvegardé: {state_file}")
|
||||
|
||||
# Charger
|
||||
loaded_state = manager.load_screen_state(screen_state.screen_state_id)
|
||||
assert loaded_state is not None
|
||||
assert loaded_state.screen_state_id == screen_state.screen_state_id
|
||||
print(f"✓ Screen state chargé: {loaded_state.screen_state_id}")
|
||||
|
||||
# Charger l'embedding
|
||||
loaded_embedding = manager.load_embedding(screen_state.state_embedding.vector_id)
|
||||
assert loaded_embedding is not None
|
||||
assert np.allclose(test_embedding, loaded_embedding)
|
||||
print(f"✓ Embedding chargé et vérifié")
|
||||
|
||||
# Lister
|
||||
state_ids = manager.list_screen_states(session_id="test_session_001")
|
||||
assert len(state_ids) > 0
|
||||
print(f"✓ Listage: {len(state_ids)} screen states trouvés")
|
||||
|
||||
return manager
|
||||
|
||||
|
||||
def test_workflow_adapter():
|
||||
"""Test de l'adaptateur de workflow."""
|
||||
print("\n" + "=" * 70)
|
||||
print("TEST 4: WorkflowStateAdapter (compatibilité arrière)")
|
||||
print("=" * 70)
|
||||
|
||||
logger = Logger(log_dir="test_logs")
|
||||
manager = ScreenStateManager(
|
||||
logger=logger,
|
||||
data_dir="test_data",
|
||||
mode="light"
|
||||
)
|
||||
adapter = WorkflowStateAdapter(
|
||||
screen_state_manager=manager,
|
||||
logger=logger
|
||||
)
|
||||
|
||||
print(f"✓ WorkflowStateAdapter initialisé")
|
||||
|
||||
# Créer un WorkflowStep (ancien format)
|
||||
step = WorkflowStep(
|
||||
step_id=1,
|
||||
action_type="click",
|
||||
target_description="Valider Button",
|
||||
position=(100, 200),
|
||||
window="Test App - Main Window",
|
||||
embedding=np.random.rand(512),
|
||||
screenshot=None
|
||||
)
|
||||
|
||||
print(f"✓ WorkflowStep créé (ancien format)")
|
||||
|
||||
# Convertir en EnrichedScreenState
|
||||
screen_state = adapter.workflow_step_to_screen_state(
|
||||
step=step,
|
||||
session_id="test_session",
|
||||
screenshot_path="test_data/screens/step_1.png"
|
||||
)
|
||||
|
||||
assert screen_state.window.window_title == step.window
|
||||
assert step.target_description in screen_state.perception.detected_text
|
||||
print(f"✓ Conversion WorkflowStep → EnrichedScreenState réussie")
|
||||
|
||||
# Convertir en WorkflowStep (pour compatibilité)
|
||||
converted_step = adapter.screen_state_to_workflow_step(
|
||||
screen_state=screen_state,
|
||||
step_id=1,
|
||||
action_type="click",
|
||||
position=(100, 200)
|
||||
)
|
||||
|
||||
assert converted_step.step_id == step.step_id
|
||||
assert converted_step.action_type == step.action_type
|
||||
assert converted_step.window == step.window
|
||||
print(f"✓ Conversion EnrichedScreenState → WorkflowStep réussie")
|
||||
|
||||
print(f"✓ Compatibilité arrière vérifiée")
|
||||
|
||||
|
||||
def test_compatibility():
|
||||
"""Test de compatibilité avec différents formats."""
|
||||
print("\n" + "=" * 70)
|
||||
print("TEST 5: Compatibilité multi-format")
|
||||
print("=" * 70)
|
||||
|
||||
# Test lecture de différents modes
|
||||
modes = ["light", "enriched", "complete"]
|
||||
|
||||
for mode in modes:
|
||||
window = WindowInfo(
|
||||
app_name="test_app",
|
||||
window_title="Test Window",
|
||||
screen_resolution=(1920, 1080)
|
||||
)
|
||||
|
||||
if mode == "light":
|
||||
screen_state = EnrichedScreenState.create_light_mode(
|
||||
screen_state_id=f"screen_{mode}",
|
||||
session_id="session_001",
|
||||
window=window,
|
||||
screenshot_path="data/screens/screen.png",
|
||||
image_embedding_provider="openclip_ViT-B-32",
|
||||
image_embedding_vector_id="data/embeddings/screen.npy"
|
||||
)
|
||||
else:
|
||||
screen_state = EnrichedScreenState(
|
||||
screen_state_id=f"screen_{mode}",
|
||||
timestamp=datetime.now(),
|
||||
session_id="session_001",
|
||||
window=window,
|
||||
raw=RawData(screenshot_path="data/screens/screen.png"),
|
||||
perception=PerceptionData(detected_text=[]),
|
||||
ui_elements=[],
|
||||
state_embedding=StateEmbedding(
|
||||
provider="openclip_ViT-B-32",
|
||||
vector_id="data/embeddings/screen.npy",
|
||||
components=None
|
||||
),
|
||||
context=ContextData(),
|
||||
mode=mode
|
||||
)
|
||||
|
||||
# Sérialiser et désérialiser
|
||||
json_str = screen_state.to_json()
|
||||
restored = EnrichedScreenState.from_json(json_str)
|
||||
|
||||
assert restored.mode == mode
|
||||
assert restored.screen_state_id == screen_state.screen_state_id
|
||||
print(f"✓ Mode '{mode}' compatible")
|
||||
|
||||
print(f"✓ Tous les modes sont compatibles")
|
||||
|
||||
|
||||
def cleanup():
|
||||
"""Nettoie les fichiers de test."""
|
||||
import shutil
|
||||
|
||||
if Path("test_data").exists():
|
||||
shutil.rmtree("test_data")
|
||||
if Path("test_logs").exists():
|
||||
shutil.rmtree("test_logs")
|
||||
|
||||
|
||||
def main():
|
||||
"""Exécute tous les tests."""
|
||||
print("\n" + "=" * 70)
|
||||
print("TESTS D'INTÉGRATION - PHASE 1 MODE LIGHT")
|
||||
print("UI Element Detection - Structures de Données de Base")
|
||||
print("=" * 70)
|
||||
|
||||
try:
|
||||
# Test 1: UIElement
|
||||
element = test_uielement_creation()
|
||||
|
||||
# Test 2: EnrichedScreenState
|
||||
screen_state = test_enriched_screen_state_light_mode()
|
||||
|
||||
# Test 3: ScreenStateManager
|
||||
manager = test_screen_state_manager()
|
||||
|
||||
# Test 4: WorkflowStateAdapter
|
||||
test_workflow_adapter()
|
||||
|
||||
# Test 5: Compatibilité
|
||||
test_compatibility()
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print("✓ TOUS LES TESTS RÉUSSIS!")
|
||||
print("=" * 70)
|
||||
print("\nRésumé:")
|
||||
print(" ✓ UIElement: Création, sérialisation, stabilité d'ID")
|
||||
print(" ✓ EnrichedScreenState: Mode light, sérialisation")
|
||||
print(" ✓ ScreenStateManager: Création, sauvegarde, chargement")
|
||||
print(" ✓ WorkflowStateAdapter: Compatibilité arrière")
|
||||
print(" ✓ Compatibilité: Lecture multi-format")
|
||||
print("\nPhase 1 (Mode Light) implémentée avec succès!")
|
||||
print("Les workflows existants continuent de fonctionner.")
|
||||
print("=" * 70)
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n✗ ÉCHEC DU TEST: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
finally:
|
||||
cleanup()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = main()
|
||||
sys.exit(0 if success else 1)
|
||||
Reference in New Issue
Block a user