""" VIMS Integration Tests Verifierar att alla instanser är korrekt skapade och fungerar. """ import sys import unittest from pathlib import Path # Add paths sys.path.append(str(Path(__file__).parent.parent)) sys.path.append(str(Path(__file__).parent.parent.parent / "atm-anomaly-detection" / "src")) from core.base_detector import VIMSInstanceRegistry from core.database import VIMSDatabase class TestVIMSInstances(unittest.TestCase): """Test alla VIMS-instanser.""" INSTANCES = [ "street-lighting", "bridge-inspection", "retail-analytics", "insurance-risk", "municipal-maintenance", "construction-site", "real-estate-condition", "urban-decay", "crowdsourced-verification", "data-quality", "insurance-contradiction", "continuous-monitoring", "decision-intelligence", "satellite-validation", "cost-stale-data", "contradiction-gap", "consensus-engine", "official-statistics", "preventive-maintenance", ] ATM_INSTANCE = "atm-monitoring" # Separat i atm-anomaly-detection/ def test_all_instances_exist(self): """Alla instans-kataloger ska finnas.""" base_dir = Path(__file__).parent.parent / "instances" for instance in self.INSTANCES: instance_dir = base_dir / instance self.assertTrue( instance_dir.exists(), f"Instance directory missing: {instance}" ) def test_instance_structure(self): """Varje instans ska ha korrekt struktur.""" base_dir = Path(__file__).parent.parent / "instances" for instance in self.INSTANCES: instance_dir = base_dir / instance # Kolla obligatoriska filer self.assertTrue( (instance_dir / "src" / "detector.py").exists(), f"{instance}: detector.py saknas" ) self.assertTrue( (instance_dir / "src" / "database.py").exists(), f"{instance}: database.py saknas" ) self.assertTrue( (instance_dir / "README.md").exists(), f"{instance}: README.md saknas" ) self.assertTrue( (instance_dir / "config.yaml").exists(), f"{instance}: config.yaml saknas" ) def test_detector_import(self): """Alla detektorer ska gå att importera.""" for instance in self.INSTANCES: detector_path = Path(__file__).parent.parent / "instances" / instance / "src" # Läs filen direkt istället för att importera detector_file = detector_path / "detector.py" self.assertTrue( detector_file.exists(), f"{instance}: detector.py saknas" ) content = detector_file.read_text() # Kolla att det finns en detektor-klass self.assertIn( "class ", content, f"{instance}: Ingen klass definierad" ) self.assertIn( "VIMSBaseDetector", content, f"{instance}: Ärver inte från VIMSBaseDetector" ) def test_database_creation(self): """Databas ska gå att skapa för varje instans.""" import tempfile import shutil for instance in self.INSTANCES: # Skapa temp-db temp_dir = tempfile.mkdtemp() db_path = Path(temp_dir) / f"{instance}.db" try: db = VIMSDatabase(instance, db_dir=temp_dir) # Läs anomaly classes från config config_path = Path(__file__).parent.parent / "instances" / instance / "config.yaml" if config_path.exists(): import yaml with open(config_path) as f: config = yaml.safe_load(f) classes = config.get("anomaly_classes", ["test"]) else: classes = ["test"] # Skapa schema db.create_schema(anomaly_classes=classes) # Verifiera att tabeller skapades import sqlite3 conn = sqlite3.connect(str(db_path)) cursor = conn.cursor() cursor.execute(f"SELECT name FROM sqlite_master WHERE type='table'") tables = [row[0] for row in cursor.fetchall()] expected_prefix = instance.replace("-", "_") self.assertIn( f"{expected_prefix}_detections", tables, f"{instance}: detections-tabell saknas" ) self.assertIn( f"{expected_prefix}_assets", tables, f"{instance}: assets-tabell saknas" ) conn.close() finally: shutil.rmtree(temp_dir) def test_config_validity(self): """Alla config-filer ska vara giltiga YAML.""" import yaml for instance in self.INSTANCES: config_path = Path(__file__).parent.parent / "instances" / instance / "config.yaml" with open(config_path) as f: config = yaml.safe_load(f) self.assertIn("topic", config, f"{instance}: topic saknas i config") self.assertIn("display_name", config, f"{instance}: display_name saknas") self.assertIn("anomaly_classes", config, f"{instance}: anomaly_classes saknas") self.assertTrue( len(config["anomaly_classes"]) > 0, f"{instance}: Inga anomaly_classes definierade" ) def test_article_links(self): """Alla instanser ska ha giltiga artikel-länkar.""" import yaml for instance in self.INSTANCES: config_path = Path(__file__).parent.parent / "instances" / instance / "config.yaml" with open(config_path) as f: config = yaml.safe_load(f) article_url = config.get("article_url", "") # Kolla att artikeln finns på disk article_path = Path(__file__).parent.parent.parent / "landvex-site" / "insights" # Extrahera slug från URL slug = article_url.strip("/").split("/")[-1] if slug: article_dir = article_path / slug self.assertTrue( article_dir.exists() or article_url.startswith("/insights/"), f"{instance}: Artikel saknas: {article_url}" ) class TestATMCore(unittest.TestCase): """Test ATM-anomaly kärnan.""" def test_detector_initialization(self): """ATM-detektor ska gå att initiera.""" # Kolla att filen finns (ultralytics krävs för att importera) detector_file = Path(__file__).parent.parent.parent / "atm-anomaly-detection" / "src" / "models" / "anomaly_detector.py" self.assertTrue(detector_file.exists(), "ATM detector file missing") # Kolla att klassen finns definierad content = detector_file.read_text() self.assertIn("class ATMAnomalyDetector", content, "ATMAnomalyDetector class missing") self.assertIn("CLASS_NAMES", content, "CLASS_NAMES missing") def test_database_setup(self): """ATM-databas ska gå att sätta upp.""" import tempfile import shutil temp_dir = tempfile.mkdtemp() try: db = VIMSDatabase("atm-monitoring", db_dir=temp_dir) db.create_schema(anomaly_classes=[ "skimming_device", "vandalism", "physical_damage" ]) # Verifiera stats = db.get_stats() self.assertIn("total_detections", stats) finally: shutil.rmtree(temp_dir) class TestAPIEndpoints(unittest.TestCase): """Test API-endpoints.""" def test_health_endpoint(self): """Health endpoint ska returnera OK.""" # Detta kräver att servern körs # Placeholder för integrationstest pass def run_all_tests(): """Kör alla tester och rapportera.""" loader = unittest.TestLoader() suite = unittest.TestSuite() suite.addTests(loader.loadTestsFromTestCase(TestVIMSInstances)) suite.addTests(loader.loadTestsFromTestCase(TestATMCore)) suite.addTests(loader.loadTestsFromTestCase(TestAPIEndpoints)) runner = unittest.TextTestRunner(verbosity=2) result = runner.run(suite) return result.wasSuccessful() if __name__ == "__main__": success = run_all_tests() sys.exit(0 if success else 1)