Files
rpa_vision_v3/test_documentation_real_utils.py
Dom a27b74cf22 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>
2026-01-29 11:23:51 +01:00

367 lines
14 KiB
Python

#!/usr/bin/env python3
"""
Real Functionality Test Utilities for Documentation System
Provides utilities for testing real documentation functionality without mocks:
- Real API integration testing
- Real data validation
- Real service management
- Real user workflow simulation
"""
import json
import requests
import subprocess
import time
from pathlib import Path
from typing import Dict, List, Optional, Any
class RealDocumentationData:
"""Manages real documentation data for testing"""
@staticmethod
def get_sample_real_data() -> List[Dict[str, Any]]:
"""Get sample documentation data that matches real RPA Vision V3 system structure"""
return [
{
"id": "screen_capture",
"name": "Screen Capture",
"description": "Captures screenshots for RPA Vision V3 analysis using Layer 0 components",
"category": "Layer 0 - Raw Capture",
"rpa_layer": 0,
"parameters": [
{"name": "region", "type": "bbox", "required": False},
{"name": "format", "type": "string", "default": "png"}
],
"examples": [
{"description": "Full screen capture", "code": "capture_screen()"},
{"description": "Region capture", "code": "capture_screen(region=(0,0,800,600))"}
],
"related_components": ["core.capture.screen_capturer", "agent_v0.screen_capturer"]
},
{
"id": "ui_detection",
"name": "UI Element Detection",
"description": "Detects UI elements using OWL-ViT and VLM models for semantic understanding",
"category": "Layer 2 - UI Detection",
"rpa_layer": 2,
"parameters": [
{"name": "screenshot", "type": "image", "required": True},
{"name": "target_description", "type": "string", "required": True},
{"name": "confidence_threshold", "type": "float", "default": 0.8}
],
"examples": [
{"description": "Detect button", "code": "detect_ui(screenshot, 'Submit button')"},
{"description": "Find input field", "code": "detect_ui(screenshot, 'username input', 0.9)"}
],
"related_components": ["core.detection.ui_detector", "core.detection.owl_detector"]
},
{
"id": "embedding_fusion",
"name": "Multi-modal Embedding Fusion",
"description": "Combines visual, textual, and spatial embeddings for robust matching",
"category": "Layer 3 - State Embedding",
"rpa_layer": 3,
"parameters": [
{"name": "image_embedding", "type": "ndarray", "required": True},
{"name": "text_embedding", "type": "ndarray", "required": True},
{"name": "weights", "type": "dict", "default": {"image": 0.6, "text": 0.4}}
],
"examples": [
{"description": "Fuse embeddings", "code": "fusion_engine.fuse({'image': img_emb, 'text': txt_emb})"}
],
"related_components": ["core.embedding.fusion_engine", "core.embedding.faiss_manager"]
},
{
"id": "workflow_execution",
"name": "Workflow Execution with Self-Healing",
"description": "Executes RPA workflows with automatic adaptation to UI changes",
"category": "Layer 4 - Workflow Execution",
"rpa_layer": 4,
"parameters": [
{"name": "workflow_graph", "type": "WorkflowGraph", "required": True},
{"name": "healing_enabled", "type": "boolean", "default": True},
{"name": "max_retries", "type": "int", "default": 3}
],
"examples": [
{"description": "Execute workflow", "code": "execute_workflow(workflow_graph)"},
{"description": "Execute with healing", "code": "execute_workflow(workflow_graph, healing_enabled=True)"}
],
"related_components": ["core.execution.action_executor", "core.healing.healing_engine"]
}
]
@staticmethod
def create_real_documentation_file(file_path: Path) -> None:
"""Create a real documentation file for testing"""
data = RealDocumentationData.get_sample_real_data()
file_path.parent.mkdir(parents=True, exist_ok=True)
with open(file_path, 'w') as f:
json.dump(data, f, indent=2)
@staticmethod
def validate_documentation_structure(data: List[Dict[str, Any]]) -> bool:
"""Validate that documentation data has correct real RPA Vision V3 structure"""
required_fields = ['id', 'name', 'description', 'category']
rpa_specific_fields = ['rpa_layer', 'related_components']
for entry in data:
# Check basic required fields
if not all(field in entry for field in required_fields):
return False
# Validate parameters if present
if 'parameters' in entry:
for param in entry['parameters']:
if not all(field in param for field in ['name', 'type']):
return False
# Check for RPA Vision V3 specific fields (at least some entries should have them)
if any(field in entry for field in rpa_specific_fields):
# Validate RPA layer is valid (0-4)
if 'rpa_layer' in entry:
if not isinstance(entry['rpa_layer'], int) or not (0 <= entry['rpa_layer'] <= 4):
return False
# Validate related components format
if 'related_components' in entry:
if not isinstance(entry['related_components'], list):
return False
# Check component naming follows RPA Vision V3 conventions
for component in entry['related_components']:
if not isinstance(component, str) or not component.startswith('core.'):
return False
return True
class RealServiceManager:
"""Manages real services for testing"""
def __init__(self, base_dir: Path = None):
self.base_dir = base_dir or Path.cwd()
self.processes = {}
def start_backend_service(self, port: int = 5000) -> bool:
"""Start real backend service"""
backend_dir = self.base_dir / "visual_workflow_builder" / "backend"
if not backend_dir.exists():
print(f"Backend directory not found: {backend_dir}")
return False
try:
# Check if already running
if self._is_port_in_use(port):
print(f"Backend already running on port {port}")
return True
# Start backend
process = subprocess.Popen(
["python", "app.py"],
cwd=backend_dir,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env={**os.environ, "FLASK_ENV": "testing", "PORT": str(port)}
)
self.processes['backend'] = process
# Wait for service to be ready
return self._wait_for_service(f"http://localhost:{port}", timeout=30)
except Exception as e:
print(f"Failed to start backend: {e}")
return False
def start_frontend_service(self, port: int = 3000) -> bool:
"""Start real frontend service"""
frontend_dir = self.base_dir / "visual_workflow_builder" / "frontend"
if not frontend_dir.exists():
print(f"Frontend directory not found: {frontend_dir}")
return False
try:
# Check if already running
if self._is_port_in_use(port):
print(f"Frontend already running on port {port}")
return True
# Start frontend
process = subprocess.Popen(
["npm", "start"],
cwd=frontend_dir,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
env={**os.environ, "PORT": str(port), "BROWSER": "none"}
)
self.processes['frontend'] = process
# Wait for service to be ready
return self._wait_for_service(f"http://localhost:{port}", timeout=60)
except Exception as e:
print(f"Failed to start frontend: {e}")
return False
def _is_port_in_use(self, port: int) -> bool:
"""Check if port is in use"""
try:
response = requests.get(f"http://localhost:{port}", timeout=2)
return True
except:
return False
def _wait_for_service(self, url: str, timeout: int = 30) -> bool:
"""Wait for service to be ready"""
start_time = time.time()
while time.time() - start_time < timeout:
try:
response = requests.get(url, timeout=2)
if response.status_code == 200:
return True
except:
pass
time.sleep(1)
return False
def cleanup(self):
"""Cleanup all started processes"""
for name, process in self.processes.items():
try:
process.terminate()
process.wait(timeout=5)
print(f"Stopped {name} service")
except:
try:
process.kill()
except:
pass
class RealAPITester:
"""Tests real API functionality"""
def __init__(self, base_url: str):
self.base_url = base_url.rstrip('/')
def test_documentation_endpoints(self) -> Dict[str, Any]:
"""Test real documentation API endpoints"""
results = {
'tools_endpoint': False,
'categories_endpoint': False,
'search_endpoint': False,
'data_valid': False,
'response_time_ok': False
}
# Test tools endpoint
try:
start_time = time.time()
response = requests.get(f"{self.base_url}/api/documentation/tools", timeout=10)
response_time = time.time() - start_time
if response.status_code == 200:
results['tools_endpoint'] = True
results['response_time_ok'] = response_time < 2.0 # Should be fast
data = response.json()
results['data_valid'] = RealDocumentationData.validate_documentation_structure(data)
except Exception as e:
print(f"Tools endpoint error: {e}")
# Test categories endpoint
try:
response = requests.get(f"{self.base_url}/api/documentation/categories", timeout=10)
results['categories_endpoint'] = response.status_code == 200
except Exception as e:
print(f"Categories endpoint error: {e}")
# Test search endpoint
try:
response = requests.get(f"{self.base_url}/api/documentation/search?q=click", timeout=10)
results['search_endpoint'] = response.status_code == 200
except Exception as e:
print(f"Search endpoint error: {e}")
return results
def get_real_documentation_data(self) -> Optional[List[Dict[str, Any]]]:
"""Get real documentation data from API"""
try:
response = requests.get(f"{self.base_url}/api/documentation/tools", timeout=10)
if response.status_code == 200:
return response.json()
except Exception as e:
print(f"Failed to get documentation data: {e}")
return None
class RealUserWorkflowTester:
"""Tests real user workflows"""
@staticmethod
def validate_tab_interaction(driver, tab_element) -> bool:
"""Validate real tab interaction behavior"""
try:
# Get initial state
initial_selected = tab_element.get_attribute("aria-selected") == "true"
# Click tab
driver.execute_script("arguments[0].click();", tab_element)
time.sleep(1)
# Verify state changed
final_selected = tab_element.get_attribute("aria-selected") == "true"
return final_selected and not initial_selected
except Exception as e:
print(f"Tab interaction validation failed: {e}")
return False
@staticmethod
def validate_content_loading(driver, expected_data: List[Dict[str, Any]]) -> bool:
"""Validate that real content loaded correctly"""
try:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
wait = WebDriverWait(driver, 10)
# Wait for content panel
content_panel = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "[role='tabpanel'], .documentation-content"))
)
if not content_panel.is_displayed():
return False
# Check for expected content
content_text = content_panel.text.lower()
# Verify at least some expected entries are present
found_count = 0
for entry in expected_data[:3]: # Check first 3 entries
if entry['name'].lower() in content_text:
found_count += 1
return found_count > 0
except Exception as e:
print(f"Content loading validation failed: {e}")
return False
# Import os for environment variables
import os