- 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>
350 lines
14 KiB
Python
350 lines
14 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Test système complet du projet RPA Vision V3
|
|
Auteur : Dom, Alice, Kiro - 8 janvier 2026
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import subprocess
|
|
import requests
|
|
import time
|
|
import json
|
|
from pathlib import Path
|
|
|
|
class TestSystemeComplet:
|
|
"""Classe pour tester l'ensemble du système RPA Vision V3"""
|
|
|
|
def __init__(self):
|
|
self.backend_url = 'http://localhost:5002'
|
|
self.resultats = {}
|
|
|
|
def tester_backend_sante(self):
|
|
"""Tester la santé du backend"""
|
|
print("🏥 Test de santé du backend...")
|
|
|
|
try:
|
|
response = requests.get(f'{self.backend_url}/health', timeout=5)
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
print(f" ✅ Backend en bonne santé: {data}")
|
|
self.resultats['backend_sante'] = True
|
|
return True
|
|
else:
|
|
print(f" ❌ Backend répond avec le code {response.status_code}")
|
|
self.resultats['backend_sante'] = False
|
|
return False
|
|
except Exception as e:
|
|
print(f" ❌ Impossible de contacter le backend: {e}")
|
|
self.resultats['backend_sante'] = False
|
|
return False
|
|
|
|
def tester_api_workflows(self):
|
|
"""Tester l'API des workflows"""
|
|
print("📋 Test de l'API workflows...")
|
|
|
|
try:
|
|
# Test GET workflows
|
|
response = requests.get(f'{self.backend_url}/api/workflows/', timeout=10)
|
|
if response.status_code == 200:
|
|
workflows = response.json()
|
|
print(f" ✅ Liste des workflows récupérée: {len(workflows)} workflows")
|
|
|
|
# Test CREATE workflow
|
|
nouveau_workflow = {
|
|
"name": "Test Workflow Système",
|
|
"description": "Workflow de test pour validation système",
|
|
"created_by": "test_system",
|
|
"nodes": [
|
|
{
|
|
"id": "test_node_1",
|
|
"type": "capture",
|
|
"position": {"x": 100, "y": 100},
|
|
"data": {"label": "Capture de test"}
|
|
}
|
|
],
|
|
"edges": [],
|
|
"variables": [
|
|
{"name": "test_var", "value": "test_value", "type": "string"}
|
|
]
|
|
}
|
|
|
|
response = requests.post(f'{self.backend_url}/api/workflows/',
|
|
json=nouveau_workflow, timeout=10)
|
|
if response.status_code == 201:
|
|
workflow_cree = response.json()
|
|
workflow_id = workflow_cree.get('id')
|
|
print(f" ✅ Workflow créé avec ID: {workflow_id}")
|
|
|
|
# Test DELETE workflow
|
|
response = requests.delete(f'{self.backend_url}/api/workflows/{workflow_id}',
|
|
timeout=5)
|
|
if response.status_code == 200:
|
|
print(f" ✅ Workflow supprimé avec succès")
|
|
self.resultats['api_workflows'] = True
|
|
return True
|
|
else:
|
|
print(f" ⚠️ Suppression échouée: {response.status_code}")
|
|
self.resultats['api_workflows'] = False
|
|
return False
|
|
else:
|
|
print(f" ❌ Création échouée: {response.status_code}")
|
|
self.resultats['api_workflows'] = False
|
|
return False
|
|
else:
|
|
print(f" ❌ Récupération échouée: {response.status_code}")
|
|
self.resultats['api_workflows'] = False
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f" ❌ Erreur API workflows: {e}")
|
|
self.resultats['api_workflows'] = False
|
|
return False
|
|
|
|
def tester_capture_ecran(self):
|
|
"""Tester la capture d'écran réelle"""
|
|
print("📸 Test de capture d'écran...")
|
|
|
|
try:
|
|
response = requests.post(f'{self.backend_url}/api/screen-capture/capture',
|
|
json={}, timeout=15)
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
largeur = data.get('width', 0)
|
|
hauteur = data.get('height', 0)
|
|
format_img = data.get('format', 'N/A')
|
|
taille_image = len(data.get('image', ''))
|
|
|
|
print(f" ✅ Capture réussie: {largeur}x{hauteur}, format {format_img}")
|
|
print(f" 📏 Taille de l'image: {taille_image} caractères")
|
|
|
|
if largeur > 0 and hauteur > 0 and taille_image > 1000:
|
|
self.resultats['capture_ecran'] = True
|
|
return True
|
|
else:
|
|
print(f" ⚠️ Capture invalide (dimensions ou taille)")
|
|
self.resultats['capture_ecran'] = False
|
|
return False
|
|
else:
|
|
print(f" ❌ Capture échouée: {response.status_code}")
|
|
self.resultats['capture_ecran'] = False
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f" ❌ Erreur capture d'écran: {e}")
|
|
self.resultats['capture_ecran'] = False
|
|
return False
|
|
|
|
def tester_detection_elements(self):
|
|
"""Tester la détection d'éléments UI"""
|
|
print("🔍 Test de détection d'éléments...")
|
|
|
|
try:
|
|
# D'abord capturer l'écran
|
|
capture_response = requests.post(f'{self.backend_url}/api/screen-capture/capture',
|
|
json={}, timeout=15)
|
|
if capture_response.status_code != 200:
|
|
print(f" ❌ Impossible de capturer pour la détection")
|
|
self.resultats['detection_elements'] = False
|
|
return False
|
|
|
|
# Ensuite détecter les éléments
|
|
response = requests.post(f'{self.backend_url}/api/screen-capture/detect-elements',
|
|
json=capture_response.json(), timeout=20)
|
|
if response.status_code == 200:
|
|
data = response.json()
|
|
nb_elements = data.get('count', 0)
|
|
types_elements = data.get('types', [])
|
|
|
|
print(f" ✅ Détection réussie: {nb_elements} éléments")
|
|
print(f" 🏷️ Types détectés: {', '.join(types_elements)}")
|
|
|
|
if nb_elements > 0:
|
|
self.resultats['detection_elements'] = True
|
|
return True
|
|
else:
|
|
print(f" ⚠️ Aucun élément détecté")
|
|
self.resultats['detection_elements'] = False
|
|
return False
|
|
else:
|
|
print(f" ❌ Détection échouée: {response.status_code}")
|
|
self.resultats['detection_elements'] = False
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f" ❌ Erreur détection d'éléments: {e}")
|
|
self.resultats['detection_elements'] = False
|
|
return False
|
|
|
|
def tester_conformite_fichiers(self):
|
|
"""Tester la conformité des fichiers critiques"""
|
|
print("📋 Test de conformité des fichiers...")
|
|
|
|
fichiers_critiques = [
|
|
'visual_workflow_builder/frontend/src/components/RealScreenCapture/RealScreenCapture.css',
|
|
'visual_workflow_builder/quick_api_test.py',
|
|
'diagnostic_backend_complet.py',
|
|
'demarrer_backend_propre.py'
|
|
]
|
|
|
|
conformes = 0
|
|
total = len(fichiers_critiques)
|
|
|
|
for fichier in fichiers_critiques:
|
|
if os.path.exists(fichier):
|
|
with open(fichier, 'r', encoding='utf-8') as f:
|
|
contenu = f.read()
|
|
|
|
# Vérifier l'attribution (plus flexible)
|
|
if ('Auteur : Dom, Alice, Kiro' in contenu or 'Auteur: Dom, Alice, Kiro' in contenu) and '8 janvier 2026' in contenu:
|
|
print(f" ✅ {fichier}: Attribution correcte")
|
|
conformes += 1
|
|
else:
|
|
print(f" ❌ {fichier}: Attribution manquante ou incorrecte")
|
|
# Debug: afficher les premières lignes
|
|
lignes = contenu.split('\n')[:5]
|
|
print(f" Premières lignes: {lignes}")
|
|
else:
|
|
print(f" ❌ {fichier}: Fichier manquant")
|
|
|
|
taux_conformite = (conformes / total) * 100 if total > 0 else 0
|
|
print(f" 📊 Conformité: {conformes}/{total} ({taux_conformite:.1f}%)")
|
|
|
|
self.resultats['conformite_fichiers'] = taux_conformite >= 80
|
|
return taux_conformite >= 80
|
|
|
|
def tester_hook_conformite(self):
|
|
"""Tester l'existence et la validité du hook de conformité"""
|
|
print("🪝 Test du hook de conformité...")
|
|
|
|
hook_path = '.kiro/hooks/verification-conformite-complete.json'
|
|
|
|
if os.path.exists(hook_path):
|
|
try:
|
|
with open(hook_path, 'r', encoding='utf-8') as f:
|
|
hook_data = json.load(f)
|
|
|
|
# Vérifier les champs requis
|
|
champs_requis = ['eventType', 'hookAction', 'outputPrompt', 'filePatterns']
|
|
if all(champ in hook_data for champ in champs_requis):
|
|
print(f" ✅ Hook de conformité valide")
|
|
print(f" 📋 Patterns surveillés: {hook_data.get('filePatterns', 'N/A')}")
|
|
self.resultats['hook_conformite'] = True
|
|
return True
|
|
else:
|
|
print(f" ❌ Hook invalide: champs manquants")
|
|
self.resultats['hook_conformite'] = False
|
|
return False
|
|
|
|
except json.JSONDecodeError as e:
|
|
print(f" ❌ Hook invalide: JSON malformé - {e}")
|
|
self.resultats['hook_conformite'] = False
|
|
return False
|
|
else:
|
|
print(f" ❌ Hook de conformité manquant: {hook_path}")
|
|
self.resultats['hook_conformite'] = False
|
|
return False
|
|
|
|
def generer_rapport_final(self):
|
|
"""Générer le rapport final du test système"""
|
|
print("\n" + "=" * 60)
|
|
print("📊 RAPPORT FINAL DU TEST SYSTÈME")
|
|
print("=" * 60)
|
|
|
|
tests_reussis = sum(1 for resultat in self.resultats.values() if resultat)
|
|
total_tests = len(self.resultats)
|
|
taux_reussite = (tests_reussis / total_tests) * 100 if total_tests > 0 else 0
|
|
|
|
print(f"📈 Résultats globaux: {tests_reussis}/{total_tests} ({taux_reussite:.1f}%)")
|
|
print("\n📋 Détail des tests:")
|
|
|
|
for test, resultat in self.resultats.items():
|
|
icone = "✅" if resultat else "❌"
|
|
print(f" {icone} {test.replace('_', ' ').title()}")
|
|
|
|
# Déterminer le statut global
|
|
if taux_reussite == 100:
|
|
statut = "🎉 EXCELLENT - Système entièrement fonctionnel"
|
|
code_sortie = 0
|
|
elif taux_reussite >= 80:
|
|
statut = "✅ BON - Système majoritairement fonctionnel"
|
|
code_sortie = 0
|
|
elif taux_reussite >= 60:
|
|
statut = "⚠️ ACCEPTABLE - Quelques problèmes à corriger"
|
|
code_sortie = 1
|
|
else:
|
|
statut = "❌ CRITIQUE - Problèmes majeurs détectés"
|
|
code_sortie = 2
|
|
|
|
print(f"\n🏆 STATUT FINAL: {statut}")
|
|
|
|
# Recommandations
|
|
print("\n💡 Recommandations:")
|
|
if not self.resultats.get('backend_sante', True):
|
|
print(" • Démarrer le backend: python3 demarrer_backend_propre.py")
|
|
if not self.resultats.get('conformite_fichiers', True):
|
|
print(" • Corriger l'attribution des fichiers (Auteur : Dom, Alice, Kiro - 8 janvier 2026)")
|
|
if not self.resultats.get('hook_conformite', True):
|
|
print(" • Vérifier le hook de conformité dans .kiro/hooks/")
|
|
|
|
# Sauvegarder le rapport
|
|
rapport = {
|
|
'timestamp': time.time(),
|
|
'taux_reussite': taux_reussite,
|
|
'statut': statut,
|
|
'resultats': self.resultats,
|
|
'code_sortie': code_sortie
|
|
}
|
|
|
|
with open('rapport_test_systeme.json', 'w', encoding='utf-8') as f:
|
|
json.dump(rapport, f, indent=2, ensure_ascii=False)
|
|
|
|
print(f"\n📄 Rapport sauvegardé: rapport_test_systeme.json")
|
|
return code_sortie
|
|
|
|
def executer_tests_complets(self):
|
|
"""Exécuter tous les tests du système"""
|
|
print("🧪 TEST SYSTÈME COMPLET RPA VISION V3")
|
|
print("=" * 50)
|
|
|
|
# Liste des tests à exécuter
|
|
tests = [
|
|
("Santé Backend", self.tester_backend_sante),
|
|
("API Workflows", self.tester_api_workflows),
|
|
("Capture Écran", self.tester_capture_ecran),
|
|
("Détection Éléments", self.tester_detection_elements),
|
|
("Conformité Fichiers", self.tester_conformite_fichiers),
|
|
("Hook Conformité", self.tester_hook_conformite),
|
|
]
|
|
|
|
# Exécuter chaque test
|
|
for nom_test, fonction_test in tests:
|
|
print(f"\n🔬 {nom_test}")
|
|
print("-" * 30)
|
|
try:
|
|
fonction_test()
|
|
except Exception as e:
|
|
print(f" 💥 Erreur critique: {e}")
|
|
self.resultats[nom_test.lower().replace(' ', '_')] = False
|
|
|
|
# Générer le rapport final
|
|
return self.generer_rapport_final()
|
|
|
|
def main():
|
|
"""Fonction principale"""
|
|
testeur = TestSystemeComplet()
|
|
|
|
try:
|
|
code_sortie = testeur.executer_tests_complets()
|
|
print(f"\n🏁 Tests terminés (code de sortie: {code_sortie})")
|
|
return code_sortie
|
|
|
|
except KeyboardInterrupt:
|
|
print("\n⚠️ Tests interrompus par l'utilisateur")
|
|
return 130
|
|
except Exception as e:
|
|
print(f"\n💥 Erreur critique: {e}")
|
|
return 1
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main()) |