QuantumLearning/tests/test_course_flow.py

141 lines
5.2 KiB
Python

from __future__ import annotations
import json
from quantum_learning import (
canonical_course_steps,
entry_notebook_path,
project_root,
visible_notebook_root_names,
)
def _notebook_text(path):
data = json.loads(path.read_text())
return "\n".join("".join(cell.get("source", [])) for cell in data.get("cells", []))
def test_start_here_is_the_only_supported_entrypoint():
assert entry_notebook_path() == project_root() / "notebooks" / "START_HERE.ipynb"
app_script = (project_root() / "scripts" / "app.sh").read_text()
assert "lab/tree/notebooks/START_HERE.ipynb" in app_script
def test_visible_notebook_root_is_curated():
notebook_root = project_root() / "notebooks"
visible_names = sorted(path.name for path in notebook_root.iterdir() if not path.name.startswith("."))
assert visible_names == sorted(visible_notebook_root_names())
def test_reference_notebook_is_not_part_of_the_course_tree():
assert not (project_root() / "notebooks" / "PROFESSIONAL_PATH.ipynb").exists()
assert not (project_root() / "notebooks" / "reference").exists()
assert not (project_root() / "notebooks" / ".reference").exists()
def test_mainline_course_notebooks_have_navigation_guardrails():
steps = canonical_course_steps()
for index, step in enumerate(steps):
path = project_root() / step.path
text = _notebook_text(path)
assert "<!-- COURSE_NAV_TOP -->" in text
assert "<!-- COURSE_NAV_BOTTOM -->" in text
assert "What To Open Next" in text
if index == 0:
assert "This is the start of the official walkthrough" in text
if index < len(steps) - 1:
next_title = steps[index + 1].title
assert next_title in text
else:
assert "This notebook closes the official walkthrough" in text
def test_start_here_does_not_contain_stale_branching_advice():
text = _notebook_text(project_root() / "notebooks" / "START_HERE.ipynb")
assert "Read the rest of this notebook, then open `PROFESSIONAL_PATH.ipynb`." not in text
assert "Open `PROFESSIONAL_PATH.ipynb` next." not in text
assert "`00_circuit_literacy.ipynb`" not in text
assert "first-pass learner journey" not in text
assert "optional side reference" not in text
assert "COURSE_BLUEPRINT.ipynb" in text
def test_mainline_route_text_is_single_pass_and_non_branching():
notebook_paths = [
project_root() / "notebooks" / "START_HERE.ipynb",
project_root() / "notebooks" / "COURSE_BLUEPRINT.ipynb",
project_root() / "notebooks" / "COURSE_COMPLETE.ipynb",
]
banned_fragments = [
"PROFESSIONAL_PATH.ipynb",
"first-pass",
"optional side reference",
"Only then return to the later single-notebook materials as transition content",
"If this notebook still feels unstable, repeat it before you move on.",
]
for path in notebook_paths:
text = _notebook_text(path)
for fragment in banned_fragments:
assert fragment not in text
course_complete_text = _notebook_text(project_root() / "notebooks" / "COURSE_COMPLETE.ipynb")
assert "This is the end of the mandatory walkthrough." in course_complete_text
def test_notebooks_use_explicit_cell_labels_and_difficulty_scheme():
sample_paths = [
project_root() / "notebooks" / "START_HERE.ipynb",
project_root()
/ "notebooks"
/ "foundations"
/ "module_01_principles_and_circuit_literacy"
/ "lecture.ipynb",
project_root()
/ "notebooks"
/ "foundations"
/ "module_01_principles_and_circuit_literacy"
/ "lab.ipynb",
]
for path in sample_paths:
text = _notebook_text(path)
assert "MANDATORY READING" in text or "META READING" in text
assert "Difficulty 1/10" in text or "Difficulty 2/10" in text or "Difficulty 3/10" in text
lecture_text = _notebook_text(
project_root()
/ "notebooks"
/ "foundations"
/ "module_01_principles_and_circuit_literacy"
/ "lecture.ipynb"
)
assert "MANDATORY TEST" in lecture_text
assert "MANDATORY EXERCISE" in lecture_text
assert "FACULTATIVE READING" in lecture_text
assert "FACULTATIVE TEST" in lecture_text
assert "FACULTATIVE EXERCISE" in lecture_text
def test_meta_route_notebooks_do_not_offer_facultative_extensions():
for rel in ["notebooks/START_HERE.ipynb", "notebooks/COURSE_BLUEPRINT.ipynb", "notebooks/COURSE_COMPLETE.ipynb"]:
text = _notebook_text(project_root() / rel)
assert "FACULTATIVE READING" not in text
assert "FACULTATIVE TEST" not in text
assert "FACULTATIVE EXERCISE" not in text
assert "Difficulty 4/10" not in text
def test_widget_wrapper_code_cells_are_hidden_from_learners():
path = project_root() / "notebooks" / "START_HERE.ipynb"
data = json.loads(path.read_text())
hidden_wrapper_found = False
for cell in data["cells"]:
if cell["cell_type"] != "code":
continue
source = "".join(cell.get("source", []))
if "quiz_block(" in source or "reflection_box(" in source:
hidden_wrapper_found = True
assert cell.get("metadata", {}).get("jupyter", {}).get("source_hidden") is True
assert hidden_wrapper_found