feat: auto committed

This commit is contained in:
SpecialX
2026-07-10 18:57:39 +08:00
parent c09d6fb7d2
commit 9ea81f1bd7
96 changed files with 13000 additions and 392 deletions

View File

@@ -0,0 +1,126 @@
"""规则校验器测试(第一道防线)."""
import json
from src.ai.services.evaluation.rule_validator import (
MAX_QUESTION_LENGTH,
RuleValidator,
ValidationResult,
)
class TestRuleValidator:
"""RuleValidator 测试."""
def setup_method(self) -> None:
self.validator = RuleValidator()
def test_valid_json_passes(self) -> None:
"""合法 JSON 通过."""
output = json.dumps({
"question": "什么是勾股定理?",
"answer": "a² + b² = c²",
"explanation": "直角三角形两直角边的平方和等于斜边的平方",
})
result = self.validator.validate(output)
assert result.passed is True
assert result.score == 1.0
assert result.parsed is not None
def test_invalid_json_fails(self) -> None:
"""非 JSON 失败."""
result = self.validator.validate("这不是 JSON")
assert result.passed is False
assert "不是有效的 JSON" in result.errors[0]
def test_markdown_wrapped_json(self) -> None:
"""markdown 代码块包裹的 JSON 能解析."""
output = '```json\n{"question": "", "answer": ""}\n```'
result = self.validator.validate(output)
assert result.passed is True
def test_missing_question_fails(self) -> None:
"""缺少 question 字段失败."""
output = json.dumps({"answer": ""})
result = self.validator.validate(output)
assert result.passed is False
assert any("question" in e for e in result.errors)
def test_missing_answer_fails(self) -> None:
"""缺少 answer 字段失败."""
output = json.dumps({"question": ""})
result = self.validator.validate(output)
assert result.passed is False
assert any("answer" in e for e in result.errors)
def test_short_question_warning(self) -> None:
"""过短 question 产生 warning."""
output = json.dumps({"question": "ab", "answer": ""})
result = self.validator.validate(output)
assert result.passed is True
assert any("过短" in w for w in result.warnings)
assert result.score == 0.8 # 有 warning
def test_difficulty_mismatch_warning(self) -> None:
"""难度不匹配产生 warning."""
output = json.dumps({
"question": "这是一道题目",
"answer": "这是答案",
"difficulty": "easy",
})
result = self.validator.validate(output, expected_difficulty="hard")
assert result.passed is True
assert any("difficulty 不匹配" in w for w in result.warnings)
def test_invalid_difficulty_warning(self) -> None:
"""无效难度值产生 warning."""
output = json.dumps({
"question": "这是一道题目",
"answer": "这是答案",
"difficulty": "impossible",
})
result = self.validator.validate(output, expected_difficulty="easy")
assert result.passed is True
assert any("无效" in w for w in result.warnings)
def test_question_type_mismatch_warning(self) -> None:
"""题型不匹配产生 warning."""
output = json.dumps({
"question": "这是一道题目",
"answer": "这是答案",
"question_type": "single_choice",
})
result = self.validator.validate(
output, expected_question_type="essay",
)
assert result.passed is True
assert any("question_type 不匹配" in w for w in result.warnings)
def test_json_array_fails(self) -> None:
"""JSON 数组(非 dict失败."""
result = self.validator.validate('[1, 2, 3]')
assert result.passed is False
def test_long_question_warning(self) -> None:
"""过长 question 产生 warning."""
output = json.dumps({
"question": "" * (MAX_QUESTION_LENGTH + 1),
"answer": "",
})
result = self.validator.validate(output)
assert result.passed is True
assert any("过长" in w for w in result.warnings)
def test_score_no_warnings(self) -> None:
"""无 warning 时 score=1.0."""
output = json.dumps({
"question": "这是一道完整的题目",
"answer": "这是完整的答案",
})
result = self.validator.validate(output)
assert result.score == 1.0
def test_validation_result_score_failed(self) -> None:
"""失败时 score=0.0."""
result = ValidationResult(passed=False, errors=["err"])
assert result.score == 0.0