test(validators): add 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:
2026-02-03 17:14:32 +00:00
parent 9239300fd9
commit e2be3daffd
4 changed files with 742 additions and 0 deletions

View File

@@ -0,0 +1,198 @@
"""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:
"""Tests for AllOf composite validator."""
def test_all_of_passes_when_all_checks_pass(self) -> None:
"""Test that AllOf passes when all checks pass."""
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:
"""Test that AllOf fails when any check fails."""
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:
"""Test that AllOf fails when all checks fail."""
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:
"""Test AllOf with metric-based validators."""
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:
"""Test the failure summary property."""
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:
"""Test that empty checks list raises error."""
with pytest.raises(ValueError, match="cannot be empty"):
AllOf(checks=[])
def test_all_of_name_property(self) -> None:
"""Test the name property."""
validator = AllOf(checks=[length(min_chars=1)])
assert validator.name == "all_of"
def test_all_of_factory_function(self) -> None:
"""Test the all_of() factory function."""
validator = all_of(checks=[length(min_chars=1)])
assert isinstance(validator, AllOf)
class TestAnyOf:
"""Tests for AnyOf composite validator."""
def test_any_of_passes_when_any_check_passes(self) -> None:
"""Test that AnyOf passes when any check passes."""
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:
"""Test that AnyOf passes when all checks pass."""
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:
"""Test that AnyOf fails when all checks fail."""
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:
"""Test AnyOf with metric-based validators."""
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:
"""Test AnyOf with excludes validator."""
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:
"""Test that empty checks list raises error."""
with pytest.raises(ValueError, match="cannot be empty"):
AnyOf(checks=[])
def test_any_of_name_property(self) -> None:
"""Test the name property."""
validator = AnyOf(checks=[length(min_chars=1)])
assert validator.name == "any_of"
def test_any_of_factory_function(self) -> None:
"""Test the any_of() factory function."""
validator = any_of(checks=[length(min_chars=1)])
assert isinstance(validator, AnyOf)