평가 및 화면 구조 정리
This commit is contained in:
parent
1248ae8ca4
commit
391639c1de
44 changed files with 5816 additions and 4501 deletions
93
apps/api/app/test_case_worksheet_rubric.py
Normal file
93
apps/api/app/test_case_worksheet_rubric.py
Normal 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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue