sentinel / tests /test_yaml_validation.py
jeuko's picture
Sync from GitHub (main)
629a216 verified
"""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