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