studycraft / tests /test_engine.py
Joedroid's picture
fix: 3 issues — test patch target, test filesystem isolation, PLAN validate done; videopython import guard
d54af4a
Raw
History Blame Contribute Delete
3.03 kB
"""Tests for StudyCraft engine with mocked LLM."""
from pathlib import Path
from unittest.mock import MagicMock, patch
from studycraft.engine import StudyCraft
def test_run_single_chapter(tmp_path: Path):
"""Test that engine can generate a single chapter with mocked LLM."""
# Create a simple document
doc = tmp_path / "test.txt"
doc.write_text("Chapter 1: Introduction\nThis is the content of chapter one.")
# Mock LLM response
mock_response = MagicMock()
mock_response.choices[0].message.content = (
"# Chapter 1: Introduction\n\n"
"## 1. Learning Objectives\n"
"- Understand the basics\n"
"- Learn key concepts\n"
"- Apply knowledge\n\n"
"## 2. Key Concepts\n...\n\n"
"## 3. Worked Examples\n...\n\n"
"## 4. Practice Exercises\n...\n\n"
"## 5. Mini Project\n...\n\n"
"## 6. Further Reading\n...\n\n"
"---\n\n"
"## Chapter Quiz\n"
"1. Question one?\n - A) Answer A\n - B) Answer B\n"
"2. Question two?\n - A) Answer A\n - B) Answer B\n"
"3. Question three?\n - A) Answer A\n - B) Answer B\n"
"4. Question four?\n - A) Answer A\n - B) Answer B\n"
"5. Question five?\n - A) Answer A\n - B) Answer B\n"
"6. Question six?\n - A) Answer A\n - B) Answer B\n"
"7. Question seven?\n - A) Answer A\n - B) Answer B\n"
"8. Question eight?\n - A) Answer A\n - B) Answer B\n"
"9. Question nine?\n - A) Answer A\n - B) Answer B\n"
"10. Question ten?\n - A) Answer A\n - B) Answer B\n"
"\n"
"## Practice Exercises\n"
"1. Exercise one?\n - Solution: ...\n"
"2. Exercise two?\n - Solution: ...\n"
"3. Exercise three?\n - Solution: ...\n"
)
# Patch all external I/O: OpenAI, RAG indexing, web research
# Note: `research` is imported in engine.py as `from .researcher import research`,
# so we must patch it in the engine module's namespace, not the researcher module.
with (
patch("studycraft.engine.OpenAI") as MockOpenAI,
patch("studycraft.engine.RAGIndex") as MockRAG,
patch("studycraft.engine.research") as MockResearch,
):
mock_client = MockOpenAI.return_value
mock_client.chat.completions.create.return_value = mock_response
MockRAG.return_value.query.return_value = "Relevant context from document"
MockResearch.return_value = "Web research results"
craft = StudyCraft(api_key="test-key", output_dir=tmp_path / "out")
craft.rag = MockRAG.return_value # Replace RAG instance
# Run only chapter 1
result = craft.run(doc, only_chapter=1, workers=1)
# Check result contains expected formats (export: md, html, pdf/docx/epub)
assert isinstance(result, dict)
# Markdown file should exist
md_files = list(Path(craft.output_dir).glob("*.md"))
assert len(md_files) >= 1, "Markdown export missing" # noqa: PT011