File size: 4,198 Bytes
1e52a1f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | """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()
|