init: document-haness 하네스 설계
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
import unittest
|
||||
|
||||
from claridoc.models import (
|
||||
REVIEW_DIMENSIONS,
|
||||
Brief,
|
||||
DocumentType,
|
||||
ModelReview,
|
||||
PipelineConfig,
|
||||
QualityGate,
|
||||
SourcePack,
|
||||
ValidationError,
|
||||
)
|
||||
from claridoc.templates import mock_pipeline_config
|
||||
from tests.helpers import brief_dict, source_dict
|
||||
|
||||
|
||||
class ModelTests(unittest.TestCase):
|
||||
def test_valid_brief_round_trip(self) -> None:
|
||||
brief = Brief.from_dict(brief_dict())
|
||||
self.assertEqual(brief.document_type, DocumentType.TECHNICAL_BLOG)
|
||||
self.assertEqual(Brief.from_dict(brief.to_dict()).title, brief.title)
|
||||
|
||||
def test_invalid_document_type_is_rejected(self) -> None:
|
||||
data = brief_dict()
|
||||
data["document_type"] = "essay"
|
||||
with self.assertRaises(ValidationError):
|
||||
Brief.from_dict(data)
|
||||
|
||||
def test_duplicate_source_ids_are_rejected(self) -> None:
|
||||
data = source_dict()
|
||||
data["sources"].append(dict(data["sources"][0]))
|
||||
with self.assertRaises(ValidationError):
|
||||
SourcePack.from_dict(data)
|
||||
|
||||
def test_target_words_range_is_enforced(self) -> None:
|
||||
data = brief_dict()
|
||||
data["constraints"]["target_words"] = 50
|
||||
with self.assertRaises(ValidationError):
|
||||
Brief.from_dict(data)
|
||||
|
||||
def test_quality_gate_rejects_non_finite_weights(self) -> None:
|
||||
with self.assertRaises(ValidationError):
|
||||
QualityGate.from_dict({"deterministic_weight": math.nan, "model_weight": math.nan})
|
||||
|
||||
def test_pipeline_requires_explicit_reviewers(self) -> None:
|
||||
data = mock_pipeline_config()
|
||||
data["reviewers"] = []
|
||||
with self.assertRaises(ValidationError):
|
||||
PipelineConfig.from_dict(data)
|
||||
|
||||
def test_pipeline_rejects_duplicate_reviewer_roles(self) -> None:
|
||||
data = mock_pipeline_config()
|
||||
data["reviewers"].append({"role": "logic", "provider": "mock"})
|
||||
with self.assertRaises(ValidationError):
|
||||
PipelineConfig.from_dict(data)
|
||||
|
||||
def test_review_requires_every_scoring_dimension(self) -> None:
|
||||
review = self._valid_review()
|
||||
del review["dimension_scores"][REVIEW_DIMENSIONS[0]]
|
||||
with self.assertRaises(ValidationError):
|
||||
ModelReview.from_dict(review, role="logic", provider="mock")
|
||||
|
||||
def test_review_rejects_unknown_issue_severity(self) -> None:
|
||||
review = self._valid_review()
|
||||
review["issues"] = [
|
||||
{
|
||||
"section": "Mechanism",
|
||||
"problem": "A causal step is missing.",
|
||||
"why_it_matters": "The conclusion cannot be reproduced.",
|
||||
"fix": "Add the missing state transition.",
|
||||
"severity": "critical",
|
||||
}
|
||||
]
|
||||
with self.assertRaises(ValidationError):
|
||||
ModelReview.from_dict(review, role="logic", provider="mock")
|
||||
|
||||
@staticmethod
|
||||
def _valid_review() -> dict:
|
||||
return {
|
||||
"score": 90,
|
||||
"dimension_scores": {name: 90 for name in REVIEW_DIMENSIONS},
|
||||
"issues": [],
|
||||
"strengths": ["The structure is explicit."],
|
||||
"questions": [],
|
||||
}
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user