Initial commit
This commit is contained in:
147
rpa_vision_v3/tests/integration/test_error_recovery.py
Normal file
147
rpa_vision_v3/tests/integration/test_error_recovery.py
Normal file
@@ -0,0 +1,147 @@
|
||||
"""
|
||||
Tests d'intégration pour la récupération d'erreurs
|
||||
|
||||
Teste les scénarios complets de gestion d'erreurs :
|
||||
- Récupération après échec de matching
|
||||
- Récupération après target introuvable avec fallbacks
|
||||
- Récupération après violation de post-conditions
|
||||
- Détection et gestion de changements UI
|
||||
- Rollback d'actions
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from unittest.mock import Mock, patch
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
from core.execution.error_handler import ErrorHandler, RecoveryStrategy
|
||||
from core.execution.action_executor import ActionExecutor, ExecutionStatus
|
||||
from core.execution.target_resolver import TargetResolver
|
||||
from core.graph.node_matcher import NodeMatcher
|
||||
from core.models.screen_state import ScreenState, RawLevel, PerceptionLevel
|
||||
from core.models.workflow_graph import WorkflowNode, WorkflowEdge, Action, ActionType
|
||||
from core.models.ui_element import UIElement
|
||||
from core.embedding.state_embedding_builder import StateEmbeddingBuilder
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def temp_dirs():
|
||||
"""Créer des répertoires temporaires pour les tests."""
|
||||
error_dir = tempfile.mkdtemp()
|
||||
failed_matches_dir = tempfile.mkdtemp()
|
||||
yield error_dir, failed_matches_dir
|
||||
shutil.rmtree(error_dir)
|
||||
shutil.rmtree(failed_matches_dir)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def error_handler(temp_dirs):
|
||||
"""Créer ErrorHandler pour les tests."""
|
||||
error_dir, _ = temp_dirs
|
||||
return ErrorHandler(error_log_dir=error_dir)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def action_executor(error_handler):
|
||||
"""Créer ActionExecutor avec ErrorHandler."""
|
||||
target_resolver = TargetResolver()
|
||||
return ActionExecutor(
|
||||
target_resolver=target_resolver,
|
||||
error_handler=error_handler,
|
||||
verify_postconditions=True
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def node_matcher(error_handler, temp_dirs):
|
||||
"""Créer NodeMatcher avec ErrorHandler."""
|
||||
_, failed_matches_dir = temp_dirs
|
||||
embedding_builder = StateEmbeddingBuilder()
|
||||
return NodeMatcher(
|
||||
embedding_builder=embedding_builder,
|
||||
error_handler=error_handler,
|
||||
failed_matches_dir=failed_matches_dir
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_screen_state_with_button():
|
||||
"""Créer un ScreenState avec un bouton."""
|
||||
raw_level = RawLevel(
|
||||
window_title="Test App",
|
||||
screenshot_path=Path("/tmp/test.png"),
|
||||
timestamp=datetime.now()
|
||||
)
|
||||
|
||||
button = UIElement(
|
||||
element_id="btn_1",
|
||||
role="button",
|
||||
text="Submit",
|
||||
bbox=(100, 100, 200, 150)
|
||||
)
|
||||
|
||||
perception_level = PerceptionLevel(
|
||||
ui_elements=[button],
|
||||
timestamp=datetime.now()
|
||||
)
|
||||
|
||||
return ScreenState(
|
||||
raw_level=raw_level,
|
||||
perception_level=perception_level
|
||||
)
|
||||
|
||||
|
||||
class TestActionExecutorErrorRecovery:
|
||||
"""Tests de récupération d'erreurs dans ActionExecutor."""
|
||||
|
||||
def test_target_not_found_triggers_error_handler(
|
||||
self, action_executor
|
||||
):
|
||||
"""Test que target introuvable déclenche ErrorHandler."""
|
||||
# Créer un état sans le bouton attendu
|
||||
raw_level = RawLevel(
|
||||
window_title="Test App",
|
||||
screenshot_path=Path("/tmp/test.png"),
|
||||
timestamp=datetime.now()
|
||||
)
|
||||
perception_level = PerceptionLevel(ui_elements=[], timestamp=datetime.now())
|
||||
screen_state = ScreenState(raw_level=raw_level, perception_level=perception_level)
|
||||
|
||||
action = Action(
|
||||
type=ActionType.MOUSE_CLICK,
|
||||
target=Mock(role="button", text_pattern="Submit")
|
||||
)
|
||||
edge = WorkflowEdge(from_node="node_1", to_node="node_2", action=action)
|
||||
|
||||
result = action_executor.execute_edge(edge=edge, screen_state=screen_state)
|
||||
|
||||
assert result.status == ExecutionStatus.TARGET_NOT_FOUND
|
||||
stats = action_executor.get_error_statistics()
|
||||
assert stats['total_errors'] >= 1
|
||||
|
||||
|
||||
class TestNodeMatcherErrorRecovery:
|
||||
"""Tests de récupération d'erreurs dans NodeMatcher."""
|
||||
|
||||
def test_matching_failure_triggers_error_handler(
|
||||
self, node_matcher, mock_screen_state_with_button
|
||||
):
|
||||
"""Test que l'échec de matching déclenche ErrorHandler."""
|
||||
node = WorkflowNode(node_id="node_1", label="Different State")
|
||||
node.matches = Mock(return_value=(False, 0.50))
|
||||
|
||||
result = node_matcher.match(
|
||||
current_state=mock_screen_state_with_button,
|
||||
candidate_nodes=[node]
|
||||
)
|
||||
|
||||
assert result is None
|
||||
stats = node_matcher.get_error_statistics()
|
||||
assert stats['total_errors'] >= 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pytest.main([__file__, '-v'])
|
||||
81
rpa_vision_v3/tests/unit/test_ui_detector.py
Normal file
81
rpa_vision_v3/tests/unit/test_ui_detector.py
Normal file
@@ -0,0 +1,81 @@
|
||||
|
||||
-v'])e__, 'in([__fil pytest.maain__':
|
||||
me__ == '__m
|
||||
|
||||
if __na600
|
||||
<= height'] ox[' + bbbox['y']sert b as
|
||||
<= 800'] bbox['width + bbox['x'] assert 0
|
||||
> ['height'] bbox assert > 0
|
||||
dth'] x['wit bboasser
|
||||
'] >= 0box['yssert b a >= 0
|
||||
x['x'] bbossert a t.bbox
|
||||
lemenbbox = e nts:
|
||||
nt in elemeeme for el
|
||||
|
||||
image)ts(_elemenctetector.detelf.dlements = se
|
||||
e00)ge(800, 6te_test_imaelf.crea s image =""
|
||||
s."ident valxes soounding bo les b que """Test (self):
|
||||
ditylinding_box_va test_bouef
|
||||
d"
|
||||
ut of boundsfidence} olement.con{efidence on f"C \
|
||||
= 1.0, nce <onfident.c eleme0 <=0. assert ements:
|
||||
elelement in for
|
||||
(image)
|
||||
elementsetect_ector.delf.det = sements el)
|
||||
ge(est_imaelf.create_t = simage"
|
||||
" et 1."e 0entrnce est confiae la"Test qu "" self):
|
||||
ounds(onfidence_bef test_c d
|
||||
nk']
|
||||
eckbox', 'li'ch', t_inpututton', 'texype in ['bt element_t asser
|
||||
n réelledétectio lors de la fiéeera vériopriété stte pr# Ce ):
|
||||
ions.items(d_combinatin valioles d_re, valiypelement_tfor s
|
||||
ces règlespecte ecteur re le détr quefie # Véri
|
||||
|
||||
} '],
|
||||
ernal_linkion', 'extgatvi'na [k': 'lin e'],
|
||||
t', 'toggl['form_inpueckbox': 'chd'],
|
||||
sword_fielield', 'pasarch_fsenput', ' ['form_it_input': 'tex '],
|
||||
ionondary_act 'sec'submit',cel', ', 'canction'primary_aton': [ 'but ns = {
|
||||
ombinatiod_c valie
|
||||
de cohérencègles finir les r # Dé
|
||||
"""types.s et ôlence entre rreCohéerty 13: "Prop "" elf):
|
||||
sistency(sone_c_typty_roleest_properef t
|
||||
d0
|
||||
ts) >= enlen(elemassert e
|
||||
age blanch ime surut être vid # Pet)
|
||||
ts, lisance(elemensert isinst as
|
||||
ge)
|
||||
ments(imat_eler.detectoec self.detements = el()
|
||||
age_test_imcreateself.= image e."""
|
||||
mage simpl sur it détection"Tes ""):
|
||||
e_image(selfplect_on_simtest_detdef
|
||||
|
||||
elements')detect_ector, 'self.det hasattr(assert e
|
||||
Non is not.detectorlfrt se asse "
|
||||
""eur.ctteon du désatiiali init"Test ""
|
||||
elf):lization(stor_initiaest_detec def t
|
||||
hite')
|
||||
or='wight), colhe, idthB', (ww('RGrn Image.ne retu""
|
||||
".est de tgeimar une ""Crée "=600):
|
||||
=800, heightidthge(self, wate_test_imacre def
|
||||
tor()
|
||||
tecector = UIDe self.det "
|
||||
ue test.""aqchant av """Setup f):
|
||||
ethod(selup_mef set
|
||||
|
||||
d"ctor.""teur UIDe po"Tests"":
|
||||
tUIDetectores Tclass
|
||||
|
||||
|
||||
tectorIDemport U_detector in.uiore.detectioion_v3.cispa_vfrom rport Image
|
||||
L imm PIs np
|
||||
fropy at nummpor
|
||||
itest
|
||||
import py
|
||||
"""
|
||||
3.3equirementses: Rlidat- Va
|
||||
s typesrtain ce'àgnés quassieuvent être ôles ne pains r- Certs Per Type
|
||||
enest Role Uniqu: UIElemen
|
||||
Property 13 testing.
|
||||
ty-based properector avecetr UIDaires pous unit"
|
||||
Test""
|
||||
Reference in New Issue
Block a user