100 lines
4.5 KiB
Python
100 lines
4.5 KiB
Python
# ddms_compliance_suite/test_loader/loader.py
|
|
|
|
from abc import ABC, abstractmethod
|
|
from pathlib import Path
|
|
from typing import List, Union, Dict, Any
|
|
import yaml # PyYAML
|
|
import json
|
|
|
|
from ..models.test_models import TestSuite # Ensure correct path
|
|
# from ..models.test_models import TestCase # If TestCase can be loaded standalone
|
|
|
|
class LoadError(Exception):
|
|
"""Custom exception for errors during test case loading."""
|
|
pass
|
|
|
|
class BaseTestCaseLoader(ABC):
|
|
@abstractmethod
|
|
def load_suites_from_file(self, file_path: Union[str, Path]) -> List[TestSuite]:
|
|
"""Loads a list of TestSuite objects from a single file."""
|
|
pass
|
|
|
|
def load_suites_from_directory(self, directory_path: Union[str, Path], recursive: bool = False, pattern: str = "*.yaml") -> List[TestSuite]:
|
|
"""Loads TestSuite objects from all matching files in a directory."""
|
|
suites: List[TestSuite] = []
|
|
p = Path(directory_path)
|
|
|
|
if not p.is_dir():
|
|
raise LoadError(f"Directory not found: {directory_path}")
|
|
|
|
file_paths = list(p.rglob(pattern)) if recursive else list(p.glob(pattern))
|
|
|
|
for file_path in file_paths:
|
|
if file_path.is_file():
|
|
try:
|
|
# Ensure that the loader instance calls its own method
|
|
# This part might need adjustment if called directly on BaseTestCaseLoader
|
|
# For now, assuming it's called from a concrete instance like YAMLTestCaseLoader
|
|
suites.extend(self.load_suites_from_file(file_path))
|
|
except LoadError as e:
|
|
# Consider using a logger for warnings/errors
|
|
print(f"Warning: Could not load test suites from {file_path}: {e}")
|
|
except Exception as e:
|
|
print(f"Warning: An unexpected error occurred loading {file_path}: {e}")
|
|
return suites
|
|
|
|
class YAMLTestCaseLoader(BaseTestCaseLoader):
|
|
def load_suites_from_file(self, file_path: Union[str, Path]) -> List[TestSuite]:
|
|
file_p = Path(file_path)
|
|
if not file_p.exists() or not file_p.is_file():
|
|
raise LoadError(f"Test case file not found or is not a file: {file_path}")
|
|
|
|
try:
|
|
with open(file_p, 'r', encoding='utf-8') as f:
|
|
data = yaml.safe_load(f)
|
|
except yaml.YAMLError as e:
|
|
raise LoadError(f"Error parsing YAML file {file_p}: {e}")
|
|
except Exception as e:
|
|
raise LoadError(f"An unexpected error occurred while reading {file_p}: {e}")
|
|
|
|
if data is None: # Handle empty YAML file
|
|
return []
|
|
|
|
if not isinstance(data, dict) or "test_suites" not in data:
|
|
raise LoadError(f"Invalid format in {file_p}: Missing 'test_suites' top-level key or not a dictionary.")
|
|
|
|
suite_data_list = data.get("test_suites") # Use .get for safer access
|
|
if not isinstance(suite_data_list, list):
|
|
raise LoadError(f"Invalid format in {file_p}: 'test_suites' must be a list.")
|
|
|
|
loaded_suites: List[TestSuite] = []
|
|
for i, suite_data in enumerate(suite_data_list):
|
|
if not isinstance(suite_data, dict):
|
|
print(f"Warning: Suite data #{i+1} in {file_p} is not a dictionary, skipping.")
|
|
continue
|
|
try:
|
|
suite = TestSuite.model_validate(suite_data) # For Pydantic v2+
|
|
# For Pydantic v1, use: suite = TestSuite.parse_obj(suite_data)
|
|
loaded_suites.append(suite)
|
|
except Exception as e: # Catch Pydantic validation errors and others
|
|
# It's often better to log this and continue, or collect all errors
|
|
raise LoadError(f"Error validating test suite #{i+1} (ID: {suite_data.get('id', 'N/A')}) in {file_p}: {e}")
|
|
|
|
return loaded_suites
|
|
|
|
# Example Usage (conceptual):
|
|
# if __name__ == '__main__':
|
|
# yaml_loader = YAMLTestCaseLoader()
|
|
# try:
|
|
# # suites_from_single_file = yaml_loader.load_suites_from_file('path/to/your/single_test_suite_file.yaml')
|
|
# # for suite in suites_from_single_file:
|
|
# # print(f"Loaded Suite: {suite.name}")
|
|
|
|
# all_suites_in_dir = yaml_loader.load_suites_from_directory('path/to/test_suites_directory', recursive=True, pattern="*.test_suite.yaml")
|
|
# for suite in all_suites_in_dir:
|
|
# print(f"Loaded Suite from Dir: {suite.name}")
|
|
# for tc in suite.test_cases:
|
|
# print(f" - TestCase: {tc.name}")
|
|
|
|
# except LoadError as e:
|
|
# print(f"Loading Error: {e}") |