validator tests

Add comprehensive tests for metric validators, constraint validators,
and composite validators covering pass/fail cases and error handling.
This commit is contained in:
2025-03-29 13:30:23 +00:00
parent 8fd1dc4cd3
commit 7f23586406
4 changed files with 723 additions and 0 deletions

View File

@@ -0,0 +1,178 @@
"""Tests for composite validators."""
import pytest
from veritext.core.types import ValidationContext
from veritext.validators import all_of, any_of, bleu, contains, excludes, length
from veritext.validators.composite import AllOf, AnyOf
class TestAllOf:
def test_all_of_passes_when_all_checks_pass(self) -> None:
validator = AllOf(
checks=[
length(min_words=2),
contains(patterns=["hello"]),
]
)
context = ValidationContext()
result = validator.check("hello world", context)
assert result.passed is True
assert len(result.checks) == 2
assert all(c.passed for c in result.checks)
def test_all_of_fails_when_one_check_fails(self) -> None:
validator = AllOf(
checks=[
length(min_words=2),
contains(patterns=["goodbye"]),
]
)
context = ValidationContext()
result = validator.check("hello world", context)
assert result.passed is False
assert len(result.checks) == 2
assert len(result.failed_checks) == 1
def test_all_of_fails_when_all_checks_fail(self) -> None:
validator = AllOf(
checks=[
length(min_words=10),
contains(patterns=["goodbye"]),
]
)
context = ValidationContext()
result = validator.check("hello", context)
assert result.passed is False
assert len(result.failed_checks) == 2
def test_all_of_with_metric_validators(self) -> None:
validator = AllOf(
checks=[
bleu(min_score=0.5),
length(min_words=3),
]
)
context = ValidationContext(reference="the quick brown fox")
result = validator.check("the quick brown fox jumps", context)
assert result.passed is True
assert len(result.checks) == 2
def test_all_of_failure_summary(self) -> None:
validator = AllOf(
checks=[
length(min_words=10),
contains(patterns=["goodbye"]),
]
)
context = ValidationContext()
result = validator.check("hello", context)
summary = result.failure_summary
assert "failed" in summary.lower()
assert "length" in summary
assert "contains" in summary
def test_all_of_raises_on_empty_checks(self) -> None:
with pytest.raises(ValueError, match="cannot be empty"):
AllOf(checks=[])
def test_all_of_name_property(self) -> None:
validator = AllOf(checks=[length(min_chars=1)])
assert validator.name == "all_of"
def test_all_of_factory_function(self) -> None:
validator = all_of(checks=[length(min_chars=1)])
assert isinstance(validator, AllOf)
class TestAnyOf:
def test_any_of_passes_when_any_check_passes(self) -> None:
validator = AnyOf(
checks=[
length(min_words=10), # Will fail
contains(patterns=["hello"]), # Will pass
]
)
context = ValidationContext()
result = validator.check("hello world", context)
assert result.passed is True
assert len(result.checks) == 2
# At least one check passed
assert any(c.passed for c in result.checks)
def test_any_of_passes_when_all_checks_pass(self) -> None:
validator = AnyOf(
checks=[
length(min_words=2),
contains(patterns=["hello"]),
]
)
context = ValidationContext()
result = validator.check("hello world", context)
assert result.passed is True
assert all(c.passed for c in result.checks)
def test_any_of_fails_when_all_checks_fail(self) -> None:
validator = AnyOf(
checks=[
length(min_words=10),
contains(patterns=["goodbye"]),
]
)
context = ValidationContext()
result = validator.check("hello", context)
assert result.passed is False
assert not any(c.passed for c in result.checks)
def test_any_of_with_metric_validators(self) -> None:
validator = AnyOf(
checks=[
bleu(min_score=0.9), # Might fail
length(min_words=3), # Should pass
]
)
context = ValidationContext(reference="different text entirely")
result = validator.check("the quick brown fox jumps", context)
assert result.passed is True # Length check passes
def test_any_of_with_excludes(self) -> None:
validator = AnyOf(
checks=[
excludes(patterns=["error"]),
excludes(patterns=["warning"]),
]
)
context = ValidationContext()
# Should pass - neither pattern found
result = validator.check("All is well", context)
assert result.passed is True
# Should pass - one pattern found, other not
result = validator.check("This is an error", context)
assert result.passed is True
# Should fail - both patterns found
result = validator.check("error and warning", context)
assert result.passed is False
def test_any_of_raises_on_empty_checks(self) -> None:
with pytest.raises(ValueError, match="cannot be empty"):
AnyOf(checks=[])
def test_any_of_name_property(self) -> None:
validator = AnyOf(checks=[length(min_chars=1)])
assert validator.name == "any_of"
def test_any_of_factory_function(self) -> None:
validator = any_of(checks=[length(min_chars=1)])
assert isinstance(validator, AnyOf)