feat(core): add verified Russian C-SSRS Recent source content
CI / ruff · pytest (pull_request) Successful in 31s
CI / ruff · pytest (pull_request) Successful in 31s
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
"""Protect the reviewed PDF transcription and its connection to Recent scoring."""
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from itertools import product
|
||||
from pathlib import Path
|
||||
|
||||
from app.core.cssrs_content import load_cssrs_russian
|
||||
from app.core.questionnaire import score_cssrs_recent
|
||||
|
||||
CLINICAL = Path(__file__).resolve().parents[1] / "docs" / "clinical"
|
||||
|
||||
|
||||
def test_source_hashes_and_complete_transcription():
|
||||
form = load_cssrs_russian()
|
||||
manifest = json.loads((CLINICAL / "review-status.json").read_text())["cssrs_russian_pdf"]
|
||||
assert hashlib.sha256((CLINICAL / manifest["file"]).read_bytes()).hexdigest() == manifest["sha256"]
|
||||
source = (CLINICAL / manifest["source_text"]).read_bytes()
|
||||
assert hashlib.sha256(source).hexdigest() == manifest["source_text_sha256"]
|
||||
assert form.version == manifest["content_version"]
|
||||
# Reconstruct the complete extracted page, including numbering, guidance,
|
||||
# original typos, answer order and the color legend. No wording is dropped.
|
||||
blocks = [form.title, form.subtitle, form.period_label_original, form.initial_instruction]
|
||||
blocks.extend(option.label for option in form.options)
|
||||
for index, item in enumerate(form.items):
|
||||
blocks.append(f"{index + 1}. {item.text}" if index < 6 else item.text)
|
||||
if item.interviewer_guidance:
|
||||
blocks.append(item.interviewer_guidance)
|
||||
if item.id == "q2":
|
||||
blocks.append(form.branch_instruction)
|
||||
blocks.extend(["Low Risk", "Moderate Risk", "High Risk"])
|
||||
assert " ".join(blocks) == source.decode().strip()
|
||||
assert [item.recall_period for item in form.items] == ["past_month"] * 5 + ["lifetime", "past_3_months"]
|
||||
|
||||
|
||||
def test_all_source_branches_and_color_categories_match_scorer():
|
||||
form = load_cssrs_russian()
|
||||
colors = {item.id: item.yes_risk for item in form.items}
|
||||
assert list(colors.values()) == ["low", "low", "moderate", "high", "high", "moderate", "high"]
|
||||
levels = ["none", "low", "moderate", "high"]
|
||||
for values in product((0, 1), repeat=7):
|
||||
all_answers = dict(zip(colors, values, strict=True))
|
||||
asked = ["q1", "q2"]
|
||||
if all_answers["q2"]:
|
||||
asked.extend(["q3", "q4", "q5"])
|
||||
asked.append("q6_lifetime")
|
||||
if all_answers["q6_lifetime"]:
|
||||
asked.append("q6_recent")
|
||||
answers = {}
|
||||
for item_id in asked:
|
||||
partial = score_cssrs_recent(answers)
|
||||
assert not partial.complete
|
||||
assert partial.missing[0] == item_id
|
||||
answers[item_id] = all_answers[item_id]
|
||||
result = score_cssrs_recent(answers)
|
||||
expected = max((levels.index(colors[key]) for key, value in answers.items() if value), default=0)
|
||||
assert result.complete and result.risk == levels[expected]
|
||||
assert result.required == tuple(asked)
|
||||
Reference in New Issue
Block a user