lesson-agent-dev / libs /agent /tests /test_quiz_maker.py
MSG
Feat/monday 4 sprint fast (#21)
1e52a1f
Raw
History Blame Contribute Delete
4.2 kB
"""Tests for quiz-maker skill: JSON parse, fallback, and export smoke."""
from pathlib import Path
from agent.models import QuizMakerInput, QuizOutline, QuizQuestion
from agent.prompts import fallback_quiz, quiz_max_tokens, quiz_to_markdown
from agent.runner import AgentRunner
from agent.tools.quiz import create_quiz, create_quiz_docx, create_quiz_html
def test_quiz_max_tokens_scales_with_question_count():
assert quiz_max_tokens(5) == 1020
assert quiz_max_tokens(3) == 660
assert quiz_max_tokens(12) == 1536
def test_parse_quiz_outline_normalizes_count():
runner = AgentRunner()
raw = (
'{"title": "Science Quiz", "instructions": "Circle one.", "questions": ['
'{"prompt": "Q1?", "choices": ["a", "b", "c", "d"], "correct_index": 0, "explanation": "e1"},'
'{"prompt": "Q2?", "choices": ["a", "b", "c", "d"], "correct_index": 1, "explanation": "e2"},'
'{"prompt": "Q3?", "choices": ["a", "b", "c", "d"], "correct_index": 2, "explanation": "e3"}'
"]}"
)
outline = runner._parse_quiz_outline(raw, expected_questions=5)
assert len(outline.questions) == 5
assert outline.title == "Science Quiz"
def test_parse_quiz_outline_trims_extra_questions():
runner = AgentRunner()
questions = ",".join(
f'{{"prompt": "Q{i}?", "choices": ["a","b","c","d"], "correct_index": 0, "explanation": ""}}'
for i in range(1, 8)
)
raw = f'{{"title": "Long", "questions": [{questions}]}}'
outline = runner._parse_quiz_outline(raw, expected_questions=5)
assert len(outline.questions) == 5
def test_parse_quiz_outline_or_error_empty():
runner = AgentRunner()
outline, err = runner._parse_quiz_outline_or_error("", 5, None)
assert outline is None
assert "empty" in err.lower()
def test_fallback_quiz_has_requested_count():
req = QuizMakerInput(topic="Fractions", grade="5", question_count=7)
outline = fallback_quiz(req)
assert len(outline.questions) == 7
assert "Fractions" in outline.title
assert all(len(q.choices) == 4 for q in outline.questions)
def test_quiz_to_markdown_includes_answers():
outline = QuizOutline(
title="Test",
instructions="Read carefully.",
questions=[
QuizQuestion(
prompt="2+2?",
choices=["4", "3", "5", "6"],
correct_index=0,
explanation="Basic addition.",
),
QuizQuestion(
prompt="3+3?",
choices=["6", "5", "7", "8"],
correct_index=0,
explanation="Also addition.",
),
QuizQuestion(
prompt="1+1?",
choices=["2", "1", "3", "4"],
correct_index=0,
explanation="Easy.",
),
],
)
md = quiz_to_markdown(outline)
assert "2+2?" in md
assert "**Answer:** A" in md
def test_create_quiz_docx_and_html(tmp_path: Path):
outline = QuizOutline(
title="Smoke Quiz",
instructions="Circle the best answer.",
questions=[
QuizQuestion(
prompt="Sample?",
choices=["Yes", "No", "Maybe", "Sometimes"],
correct_index=0,
explanation="Because.",
),
QuizQuestion(
prompt="Another?",
choices=["A", "B", "C", "D"],
correct_index=2,
explanation="C is correct.",
),
QuizQuestion(
prompt="Third?",
choices=["1", "2", "3", "4"],
correct_index=1,
explanation="Two.",
),
],
)
docx_path = tmp_path / "quiz.docx"
html_path = tmp_path / "quiz.html"
create_quiz_docx(outline, docx_path)
create_quiz_html(outline, html_path)
assert docx_path.stat().st_size > 100
html_text = html_path.read_text(encoding="utf-8")
assert "Smoke Quiz" in html_text
assert "Answer key" in html_text
paths = create_quiz(outline, tmp_path / "out", stem="worksheet")
assert paths["docx"].exists()
assert paths["html"].exists()