"""Test YAML file validation against UserInput schema.""" from pathlib import Path import pytest import yaml from pydantic import ValidationError from sentinel.user_input import UserInput class TestYAMLValidation: """Test that all YAML files in examples/ validate against UserInput schema.""" @pytest.fixture(scope="class") def examples_directory(self) -> Path: """Get the examples directory path. Returns: Path: Path to the examples directory. """ return Path(__file__).parent.parent / "examples" @pytest.fixture(scope="class") def all_yaml_files(self, examples_directory: Path) -> list[Path]: """Get all YAML files in the examples directory. Args: examples_directory: Path to the examples directory. Returns: list[Path]: List of all YAML files found in the examples directory. """ return list(examples_directory.rglob("*.yaml")) def test_yaml_files_exist(self, all_yaml_files: list[Path]) -> None: """Test that we found YAML files to validate. Args: all_yaml_files: List of all YAML files found in the examples directory. """ assert len(all_yaml_files) > 0, "No YAML files found in examples directory" print(f"Found {len(all_yaml_files)} YAML files to validate") @pytest.mark.parametrize( "yaml_file", [ pytest.param(p, id=p.relative_to(Path(__file__).parent.parent).as_posix()) for p in (Path(__file__).parent.parent / "examples").rglob("*.yaml") ], ) def test_individual_yaml_validation(self, yaml_file: Path) -> None: """Test that each YAML file validates against UserInput schema. Args: yaml_file: Path to the YAML file to validate. """ assert yaml_file.exists(), f"YAML file does not exist: {yaml_file}" try: with yaml_file.open("r", encoding="utf-8") as file: data = yaml.safe_load(file) user_input = UserInput.model_validate(data) assert user_input is not None except yaml.YAMLError as error: pytest.fail(f"YAML parsing error in {yaml_file}: {error}") except ValidationError as error: error_details = [] for error_detail in error.errors(): field_path = " -> ".join(str(loc) for loc in error_detail["loc"]) error_details.append( f" Field '{field_path}': {error_detail['msg']} " f"(input: {error_detail.get('input', 'N/A')})" ) pytest.fail( f"Validation error in {yaml_file}:\n" + "\n".join(error_details) ) def test_all_yaml_files_valid(self, all_yaml_files: list[Path]) -> None: """Test that all YAML files are valid (batch validation). Args: all_yaml_files: List of all YAML files found in the examples directory. """ failed_files = [] for yaml_file in all_yaml_files: try: with yaml_file.open("r", encoding="utf-8") as file: data = yaml.safe_load(file) UserInput.model_validate(data) except Exception as error: failed_files.append((yaml_file, str(error))) if failed_files: error_message = "YAML validation failures:\n" for file_path, error in failed_files: error_message += f" {file_path}: {error}\n" pytest.fail(error_message) print(f"✅ All {len(all_yaml_files)} YAML files passed validation") def test_yaml_files_summary(self, all_yaml_files: list[Path]) -> None: """Test that provides a summary of all YAML files found. Args: all_yaml_files: List of all YAML files found in the examples directory. """ categories = {} for yaml_file in all_yaml_files: # Get the relative path from examples directory rel_path = yaml_file.relative_to(Path(__file__).parent.parent / "examples") category = str(rel_path.parent) if rel_path.parent != Path(".") else "root" if category not in categories: categories[category] = [] categories[category].append(rel_path.name) print(f"\nYAML Files Summary ({len(all_yaml_files)} total):") for category, files in sorted(categories.items()): print(f" {category}: {len(files)} files") for file_name in sorted(files): print(f" - {file_name}") # This test always passes - it's just for information assert True