""" Test de propriété pour l'absence d'imports circulaires. Propriété 3: Absence d'imports circulaires Pour tout module du système, l'importation ne doit pas créer de dépendances cycliques. Auteur: Dom, Alice Kiro Date: 20 décembre 2024 """ import sys from pathlib import Path from hypothesis import given, strategies as st, settings import pytest # Ajouter le répertoire racine au path sys.path.insert(0, str(Path(__file__).parent.parent.parent)) from validate_circular_imports import CircularImportDetector class TestCircularImportsProperty: """Tests de propriété pour l'absence d'imports circulaires""" @settings(max_examples=10, deadline=30000) # 10 exemples, 30s timeout @given(st.just("core")) # On teste toujours le répertoire core def test_property_no_circular_imports(self, directory_name): """ Propriété 3: Absence d'imports circulaires Pour tout module du système, l'importation ne doit pas créer de dépendances cycliques. Cette propriété garantit que: 1. Aucun cycle n'existe dans le graphe d'imports 2. Les imports peuvent être résolus dans un ordre topologique 3. Le système peut démarrer sans erreurs d'import """ root_path = Path(__file__).parent.parent.parent target_path = root_path / directory_name # Vérifier que le répertoire existe assert target_path.exists(), f"Répertoire {directory_name} non trouvé" # Analyser les imports detector = CircularImportDetector(root_path) detector.analyze_directory(target_path) # Détecter les cycles cycles = detector.find_cycles() # Propriété: Aucun cycle ne doit exister assert len(cycles) == 0, ( f"Imports circulaires détectés dans {directory_name}:\n" + "\n".join([ f"Cycle {i+1}: {' → '.join(cycle)}" for i, cycle in enumerate(cycles) ]) + "\n\nCeci viole la Propriété 3: Absence d'imports circulaires" ) # Propriété additionnelle: Le graphe doit être analysable assert len(detector.module_paths) > 0, "Aucun module analysé" # Propriété additionnelle: Les dépendances doivent être cohérentes total_deps = sum(len(deps) for deps in detector.module_graph.values()) assert total_deps >= 0, "Nombre de dépendances invalide" def test_property_lazy_imports_work(self): """ Propriété: Les imports lazy doivent fonctionner correctement Cette propriété garantit que: 1. Les fonctions de lazy loading retournent les bonnes classes 2. Les imports conditionnels ne créent pas de cycles 3. TYPE_CHECKING fonctionne comme attendu """ from core.models import ( get_workflow, get_workflow_node, get_action, get_target_spec ) # Propriété: Les fonctions lazy doivent retourner des classes valides classes = [ get_workflow(), get_workflow_node(), get_action(), get_target_spec() ] for cls in classes: assert hasattr(cls, '__name__'), "Classe sans nom" assert callable(cls), "Objet non callable" def test_property_interfaces_are_abstract(self): """ Propriété: Les interfaces doivent être abstraites Cette propriété garantit que: 1. Les interfaces ne peuvent pas être instanciées directement 2. Elles définissent des méthodes abstraites 3. Elles permettent le découplage """ from core.interfaces import ITargetResolver, IActionExecutor, IErrorHandler interfaces = [ITargetResolver, IActionExecutor, IErrorHandler] for interface in interfaces: # Propriété: Doit avoir des méthodes abstraites assert hasattr(interface, '__abstractmethods__'), ( f"{interface.__name__} n'a pas de méthodes abstraites" ) # Propriété: Ne peut pas être instanciée directement with pytest.raises(TypeError): interface() if __name__ == "__main__": pytest.main([__file__, "-v"])