168 lines
5.3 KiB
Python
168 lines
5.3 KiB
Python
"""Tests for schema validation."""
|
|
|
|
import json
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
from src.confgen.validator import SchemaValidator
|
|
|
|
|
|
class TestSchemaValidator:
|
|
"""Tests for SchemaValidator."""
|
|
|
|
def setup_method(self):
|
|
"""Set up test fixtures."""
|
|
self.schema_data = {
|
|
"type": "object",
|
|
"properties": {
|
|
"name": {"type": "string"},
|
|
"port": {"type": "integer", "minimum": 1, "maximum": 65535},
|
|
"enabled": {"type": "boolean"},
|
|
"timeout": {"type": "number", "minimum": 0},
|
|
},
|
|
"required": ["name", "port"],
|
|
}
|
|
|
|
with tempfile.NamedTemporaryFile(
|
|
mode="w", suffix=".json", delete=False
|
|
) as f:
|
|
json.dump(self.schema_data, f)
|
|
self.schema_path = f.name
|
|
|
|
self.validator = SchemaValidator(self.schema_path)
|
|
|
|
def teardown_method(self):
|
|
"""Clean up test fixtures."""
|
|
Path(self.schema_path).unlink()
|
|
|
|
def test_validate_valid_config(self):
|
|
"""Test validating a valid configuration."""
|
|
config = {"name": "myapp", "port": 8080, "enabled": True, "timeout": 30}
|
|
|
|
is_valid, errors = self.validator.validate(config)
|
|
|
|
assert is_valid is True
|
|
assert len(errors) == 0
|
|
|
|
def test_validate_missing_required_field(self):
|
|
"""Test that missing required field fails validation."""
|
|
config = {"name": "myapp"}
|
|
|
|
is_valid, errors = self.validator.validate(config)
|
|
|
|
assert is_valid is False
|
|
assert len(errors) > 0
|
|
assert any("port" in error for error in errors)
|
|
|
|
def test_validate_invalid_type(self):
|
|
"""Test that invalid type fails validation."""
|
|
config = {"name": "myapp", "port": "not_a_number"}
|
|
|
|
is_valid, errors = self.validator.validate(config)
|
|
|
|
assert is_valid is False
|
|
assert len(errors) > 0
|
|
|
|
def test_validate_integer_out_of_range(self):
|
|
"""Test that integer out of range fails validation."""
|
|
config = {"name": "myapp", "port": 70000}
|
|
|
|
is_valid, errors = self.validator.validate(config)
|
|
|
|
assert is_valid is False
|
|
assert any("minimum" in error or "maximum" in error for error in errors)
|
|
|
|
def test_validate_boolean_type(self):
|
|
"""Test validating boolean fields."""
|
|
config = {"name": "myapp", "port": 8080, "enabled": "not_boolean"}
|
|
|
|
is_valid, errors = self.validator.validate(config)
|
|
|
|
assert is_valid is False
|
|
|
|
def test_format_error_with_path(self):
|
|
"""Test error formatting includes the path."""
|
|
schema_with_nested = {
|
|
"type": "object",
|
|
"properties": {
|
|
"database": {
|
|
"type": "object",
|
|
"properties": {
|
|
"host": {"type": "string"},
|
|
"port": {"type": "integer"},
|
|
},
|
|
"required": ["host"],
|
|
},
|
|
},
|
|
}
|
|
|
|
with tempfile.NamedTemporaryFile(
|
|
mode="w", suffix=".json", delete=False
|
|
) as f:
|
|
json.dump(schema_with_nested, f)
|
|
nested_schema_path = f.name
|
|
|
|
validator = SchemaValidator(nested_schema_path)
|
|
config = {"database": {"port": "invalid"}}
|
|
|
|
is_valid, errors = validator.validate(config)
|
|
|
|
assert is_valid is False
|
|
Path(nested_schema_path).unlink()
|
|
|
|
def test_get_schema_summary(self):
|
|
"""Test getting a summary of the schema."""
|
|
summary = self.validator.get_schema_summary()
|
|
|
|
assert summary["type"] == "object"
|
|
assert "name" in summary["required"]
|
|
assert "port" in summary["properties"]
|
|
assert "type" in summary["properties"]["name"]
|
|
|
|
def test_check_property_exists(self):
|
|
"""Test checking if property exists in data."""
|
|
config = {"database": {"host": "localhost"}}
|
|
|
|
assert self.validator.check_property_exists(config, "database.host") is True
|
|
assert self.validator.check_property_exists(config, "database.port") is False
|
|
assert self.validator.check_property_exists(config, "nonexistent") is False
|
|
|
|
def test_validate_nested_object(self):
|
|
"""Test validating nested objects."""
|
|
schema = {
|
|
"type": "object",
|
|
"properties": {
|
|
"database": {
|
|
"type": "object",
|
|
"properties": {
|
|
"host": {"type": "string"},
|
|
"port": {"type": "integer"},
|
|
},
|
|
"required": ["host", "port"],
|
|
},
|
|
},
|
|
"required": ["database"],
|
|
}
|
|
|
|
with tempfile.NamedTemporaryFile(
|
|
mode="w", suffix=".json", delete=False
|
|
) as f:
|
|
json.dump(schema, f)
|
|
nested_schema_path = f.name
|
|
|
|
validator = SchemaValidator(nested_schema_path)
|
|
config = {"database": {"host": "localhost", "port": 5432}}
|
|
|
|
is_valid, errors = validator.validate(config)
|
|
|
|
assert is_valid is True
|
|
Path(nested_schema_path).unlink()
|
|
|
|
def test_validate_with_default_values(self):
|
|
"""Test that validation ignores missing optional fields."""
|
|
config = {"name": "myapp", "port": 8080}
|
|
|
|
is_valid, errors = self.validator.validate(config)
|
|
|
|
assert is_valid is True
|