OPEN SOURCE
software/tests/test_validation.py
このサイトで読み、必要なファイルを保存できます。
日常訳はAIを用いて作成された翻訳です。人間の聖書学・原語の専門家による全訳の検証は確認されていません。既存の翻訳や原語資料と照らし合わせてお読みください。
1"""Tests for validation checks."""23import pytest45from src.context.glossary import GlossaryManager6from src.models.verse import GlossaryTerm, TranslationOutput, VerseReference7from src.validation.checks import TranslationValidator, ValidationReport, ValidationResult8910@pytest.fixture11def glossary_terms() -> list[GlossaryTerm]:12"""Create test glossary terms."""13return [14GlossaryTerm(15original="λόγος",16transliteration="logos",17japanese="言葉",18english="word",19),20]212223class TestValidationResult:24"""Tests for ValidationResult."""2526def test_create_result(self) -> None:27"""Test creating a validation result."""28result = ValidationResult(29passed=True,30check_name="test_check",31message="All good",32)33assert result.passed is True34assert result.check_name == "test_check"3536def test_result_with_details(self) -> None:37"""Test result with details."""38result = ValidationResult(39passed=False,40check_name="length",41message="Too short",42details={"length": 5, "min": 10},43)44assert result.details["length"] == 5454647class TestValidationReport:48"""Tests for ValidationReport."""4950def test_empty_report(self) -> None:51"""Test empty report."""52report = ValidationReport()53assert report.all_passed is True54assert report.failed_checks == []5556def test_add_result(self) -> None:57"""Test adding results."""58report = ValidationReport()59report.add_result(60ValidationResult(passed=True, check_name="check1", message="OK")61)62assert len(report.results) == 16364def test_all_passed_true(self) -> None:65"""Test all_passed returns True when all pass."""66report = ValidationReport()67report.add_result(68ValidationResult(passed=True, check_name="check1", message="OK")69)70report.add_result(71ValidationResult(passed=True, check_name="check2", message="OK")72)73assert report.all_passed is True7475def test_all_passed_false(self) -> None:76"""Test all_passed returns False when any fail."""77report = ValidationReport()78report.add_result(79ValidationResult(passed=True, check_name="check1", message="OK")80)81report.add_result(82ValidationResult(passed=False, check_name="check2", message="Failed")83)84assert report.all_passed is False8586def test_failed_checks(self) -> None:87"""Test getting failed checks."""88report = ValidationReport()89report.add_result(90ValidationResult(passed=True, check_name="check1", message="OK")91)92report.add_result(93ValidationResult(passed=False, check_name="check2", message="Failed")94)95failed = report.failed_checks96assert len(failed) == 197assert failed[0].check_name == "check2"9899100class TestTranslationValidator:101"""Tests for TranslationValidator."""102103def test_init_defaults(self) -> None:104"""Test default initialization."""105validator = TranslationValidator()106assert validator.min_length == 5107assert validator.max_length == 2000108109def test_init_custom_params(self) -> None:110"""Test custom parameters."""111validator = TranslationValidator(min_length=10, max_length=100)112assert validator.min_length == 10113assert validator.max_length == 100114115def test_validate_valid_translation(self) -> None:116"""Test validating a valid translation."""117validator = TranslationValidator()118ref = VerseReference(book="john", chapter=1, verse=1)119output = TranslationOutput(120reference=ref,121text="初めに言葉があった。言葉は神と共にあった。",122model="test",123)124report = validator.validate(output)125assert report.all_passed is True126127def test_check_not_empty_fails(self) -> None:128"""Test not_empty check fails for empty text."""129validator = TranslationValidator()130ref = VerseReference(book="john", chapter=1, verse=1)131output = TranslationOutput(reference=ref, text="", model="test")132report = validator.validate(output)133assert not report.all_passed134failed_names = [r.check_name for r in report.failed_checks]135assert "not_empty" in failed_names136137def test_check_not_empty_whitespace_only(self) -> None:138"""Test not_empty check fails for whitespace-only text."""139validator = TranslationValidator()140ref = VerseReference(book="john", chapter=1, verse=1)141output = TranslationOutput(reference=ref, text=" \n\t ", model="test")142report = validator.validate(output)143failed_names = [r.check_name for r in report.failed_checks]144assert "not_empty" in failed_names145146def test_check_length_too_short(self) -> None:147"""Test length check fails for short text."""148validator = TranslationValidator(min_length=10)149ref = VerseReference(book="john", chapter=1, verse=1)150output = TranslationOutput(reference=ref, text="短い", model="test")151report = validator.validate(output)152failed_names = [r.check_name for r in report.failed_checks]153assert "length" in failed_names154155def test_check_length_too_long(self) -> None:156"""Test length check fails for long text."""157validator = TranslationValidator(max_length=10)158ref = VerseReference(book="john", chapter=1, verse=1)159output = TranslationOutput(160reference=ref, text="これはとても長い文章です。", model="test"161)162report = validator.validate(output)163failed_names = [r.check_name for r in report.failed_checks]164assert "length" in failed_names165166def test_check_no_english_only_fails(self) -> None:167"""Test no_english_only check fails for English-only text."""168validator = TranslationValidator()169ref = VerseReference(book="john", chapter=1, verse=1)170output = TranslationOutput(171reference=ref, text="In the beginning was the Word", model="test"172)173report = validator.validate(output)174failed_names = [r.check_name for r in report.failed_checks]175assert "no_english_only" in failed_names176177def test_check_has_japanese_low_ratio(self) -> None:178"""Test has_japanese check fails for low Japanese ratio."""179validator = TranslationValidator()180ref = VerseReference(book="john", chapter=1, verse=1)181# Mostly English with just a few Japanese182output = TranslationOutput(183reference=ref, text="This is English text あ", model="test"184)185report = validator.validate(output)186failed_names = [r.check_name for r in report.failed_checks]187assert "has_japanese" in failed_names188189def test_check_glossary_consistency_no_glossary(self) -> None:190"""Test glossary check passes without glossary."""191validator = TranslationValidator()192ref = VerseReference(book="john", chapter=1, verse=1)193output = TranslationOutput(194reference=ref,195text="初めに言葉があった。",196model="test",197glossary_terms_applied=["λόγος"],198)199report = validator.validate(output)200# Should pass since no glossary to check against201glossary_results = [202r for r in report.results if r.check_name == "glossary_consistency"203]204assert len(glossary_results) == 0 # No glossary configured205206def test_check_glossary_consistency_with_glossary(207self, glossary_terms: list[GlossaryTerm]208) -> None:209"""Test glossary check with glossary."""210glossary = GlossaryManager(glossary_terms)211validator = TranslationValidator(glossary=glossary)212ref = VerseReference(book="john", chapter=1, verse=1)213output = TranslationOutput(214reference=ref,215text="初めに言葉があった。", # Contains 言葉216model="test",217glossary_terms_applied=["λόγος"],218)219report = validator.validate(output)220glossary_results = [221r for r in report.results if r.check_name == "glossary_consistency"222]223assert len(glossary_results) == 1224assert glossary_results[0].passed is True225226def test_check_glossary_consistency_missing_term(227self, glossary_terms: list[GlossaryTerm]228) -> None:229"""Test glossary check fails for missing term."""230glossary = GlossaryManager(glossary_terms)231validator = TranslationValidator(glossary=glossary)232ref = VerseReference(book="john", chapter=1, verse=1)233output = TranslationOutput(234reference=ref,235text="初めにワードがあった。", # Missing 言葉, using ワード instead236model="test",237glossary_terms_applied=["λόγος"],238)239report = validator.validate(output)240glossary_results = [241r for r in report.results if r.check_name == "glossary_consistency"242]243assert len(glossary_results) == 1244assert glossary_results[0].passed is False245246def test_check_glossary_consistency_no_terms_applied(247self, glossary_terms: list[GlossaryTerm]248) -> None:249"""Test glossary check passes when no terms expected."""250glossary = GlossaryManager(glossary_terms)251validator = TranslationValidator(glossary=glossary)252ref = VerseReference(book="john", chapter=1, verse=1)253output = TranslationOutput(254reference=ref,255text="初めにあった。",256model="test",257glossary_terms_applied=[], # No terms expected258)259report = validator.validate(output)260glossary_results = [261r for r in report.results if r.check_name == "glossary_consistency"262]263assert len(glossary_results) == 1264assert glossary_results[0].passed is True265