평가 및 화면 구조 정리

This commit is contained in:
Yun Chan 2026-06-28 21:46:22 +09:00
parent 1248ae8ca4
commit 391639c1de
44 changed files with 5816 additions and 4501 deletions

View file

@ -0,0 +1,93 @@
import copy
import json
import subprocess
import sys
import unittest
from pathlib import Path
try:
from jsonschema import Draft202012Validator
except ModuleNotFoundError: # pragma: no cover - optional test helper dependency
Draft202012Validator = None
from app.services.case_worksheet_rubric import load_rubric, validate_rubric
from app.session_read_model import case_worksheet_template_item_keys
REPO_ROOT = Path(__file__).resolve().parents[3]
RUBRIC_PATH = REPO_ROOT / "data" / "rubrics" / "case-worksheet-rubric.json"
SCHEMA_PATH = REPO_ROOT / "data" / "rubrics" / "case-worksheet-rubric.schema.json"
SCRIPT_PATH = REPO_ROOT / "scripts" / "check-case-worksheet-rubric.py"
class CaseWorksheetRubricTests(unittest.TestCase):
def test_scaffold_matches_generated_worksheet_keys_without_enabling_scoring(self) -> None:
rubric = load_rubric(RUBRIC_PATH)
report = validate_rubric(rubric, expected_item_keys=case_worksheet_template_item_keys())
self.assertTrue(report["passed"], report)
self.assertEqual(report["schema_version"], "vignette.case_worksheet_rubric.v1")
self.assertEqual(report["status"], "scaffold_only")
self.assertFalse(report["scoring_enabled"])
self.assertEqual(report["sections_total"], 5)
self.assertEqual(report["items_total"], 28)
self.assertGreaterEqual(len(report["warnings"]), 20)
self._validate_with_schema(rubric, SCHEMA_PATH)
def test_scoring_requires_clinical_approval(self) -> None:
rubric = load_rubric(RUBRIC_PATH)
draft = copy.deepcopy(rubric)
draft["status"] = "draft"
draft["scoring_enabled"] = True
report = validate_rubric(draft, expected_item_keys=case_worksheet_template_item_keys())
self.assertFalse(report["passed"])
self.assertIn("scoring_enabled requires status=approved", report["errors"])
def test_missing_worksheet_item_fails_validation(self) -> None:
rubric = load_rubric(RUBRIC_PATH)
broken = copy.deepcopy(rubric)
broken["sections"][0]["items"] = broken["sections"][0]["items"][1:]
report = validate_rubric(broken, expected_item_keys=case_worksheet_template_item_keys())
self.assertFalse(report["passed"])
self.assertIn("exploration_11: missing worksheet item: presenting_complaint", report["errors"])
def test_cli_reports_json(self) -> None:
completed = subprocess.run(
[
sys.executable,
"-X",
"utf8",
str(SCRIPT_PATH),
"--rubric",
str(RUBRIC_PATH),
"--json",
],
cwd=str(REPO_ROOT),
check=True,
capture_output=True,
text=True,
encoding="utf-8",
)
report = json.loads(completed.stdout)
self.assertTrue(report["passed"], report)
self.assertEqual(report["items_total"], 28)
self.assertFalse(report["scoring_enabled"])
self.assertEqual(report["rubric_path"], "data/rubrics/case-worksheet-rubric.json")
self.assertRegex(report["content_sha256"], r"^[a-f0-9]{64}$")
def _validate_with_schema(self, instance: object, schema_path: Path) -> None:
schema = json.loads(schema_path.read_text(encoding="utf-8"))
self.assertEqual(schema.get("$schema"), "https://json-schema.org/draft/2020-12/schema")
if Draft202012Validator is None:
return
Draft202012Validator.check_schema(schema)
Draft202012Validator(schema).validate(instance)
if __name__ == "__main__":
unittest.main()