studycraft / tests /test_validator.py
Joedroid's picture
style: final lint cleanups - line breaks, import ordering, test client context
ec30e3a
Raw
History Blame Contribute Delete
4.07 kB
"""Tests for studycraft.validator."""
from studycraft.validator import (
MIN_EXAMPLES,
MIN_QUIZ_QUESTIONS,
REQUIRED_SECTIONS,
validate_chapter,
validate_guide,
)
_GOOD_CHAPTER = """\
# πŸ“– Practice Guide β€” Python
## Chapter 1: Variables
## 1. Learning Objectives
- Understand variables
## 2. Core Concepts & Theory
Concepts here.
## 3. Worked Examples
### Example 1 β€” Assigning a variable
**Problem:** Assign x = 5
**Solution:** x = 5
### Example 2 β€” String variable
**Problem:** Create a name
**Solution:** name = "Alice"
### Example 3 β€” Multiple assignment
**Problem:** Assign a, b, c
**Solution:** a, b, c = 1, 2, 3
## 4. Practice Exercises
Do these exercises.
## 5. Mini Project
Build a calculator.
## 6. Chapter Quiz
1. What is a variable?
2. How do you assign a value?
3. What types exist?
4. What is an integer?
5. Given x=5, what is x+1?
6. How do you swap variables?
7. Why use descriptive names?
8. What is the difference between int and float?
9. How would you design a config system?
10. Which naming convention is better and why?
## 7. Reflection
Think about what you learned.
## 8. Tips & Common Mistakes
Avoid common errors.
"""
_BAD_CHAPTER = """\
# Chapter 1: Variables
## 1. Learning Objectives
- [Actionable objective 1]
## 2. Core Concepts & Theory
[Term 1] is important.
## 3. Worked Examples
### Example 1 β€” Basic
**Problem:** [State the problem]
"""
def test_good_chapter_passes():
result = validate_chapter(_GOOD_CHAPTER, label="Ch 1")
assert result.passed is True
assert result.missing_sections == []
assert result.example_count == MIN_EXAMPLES
assert result.quiz_count == MIN_QUIZ_QUESTIONS
assert result.placeholder_count == 0
assert result.summary() == "All checks passed"
def test_bad_chapter_missing_sections():
result = validate_chapter(_BAD_CHAPTER, label="Ch 1")
assert not result.passed
# Must be missing these specific sections
for section in ("Practice Exercises", "Mini Project", "Chapter Quiz", "Reflection", "Tips & Common Mistakes"):
assert section in result.missing_sections, f"Should report {section} as missing"
def test_bad_chapter_has_placeholders():
result = validate_chapter(_BAD_CHAPTER, label="Ch 1")
assert result.placeholder_count > 0
# Verify actual placeholder text is captured
assert any("[Actionable objective 1]" == p for p in result.placeholders)
assert any("[Term 1]" == p for p in result.placeholders)
def test_bad_chapter_low_examples():
result = validate_chapter(_BAD_CHAPTER)
assert result.example_count == 1
assert result.example_count < MIN_EXAMPLES
def test_bad_chapter_zero_quiz():
result = validate_chapter(_BAD_CHAPTER)
assert result.quiz_count == 0
def test_example_count_exact():
result = validate_chapter(_GOOD_CHAPTER)
assert result.example_count == 3
def test_quiz_count_exact():
result = validate_chapter(_GOOD_CHAPTER)
assert result.quiz_count == 10
def test_summary_lists_all_failures():
result = validate_chapter(_BAD_CHAPTER)
summary = result.summary()
assert "Missing sections" in summary
assert "Examples:" in summary
assert "Quiz questions:" in summary
assert "Unfilled placeholders:" in summary
def test_validate_guide_splits_and_validates():
ch2 = _GOOD_CHAPTER.replace("Chapter 1", "Chapter 2").replace("Practice Guide β€” Python", "Practice Guide β€” Java")
two_chapters = _GOOD_CHAPTER + "\n\n---\n\n" + ch2
results = validate_guide(two_chapters)
assert len(results) == 2
assert all(r.passed for r in results)
assert results[0].chapter_label != results[1].chapter_label
def test_validate_guide_empty():
results = validate_guide("")
assert results == []
def test_label_preserved():
result = validate_chapter(_GOOD_CHAPTER, label="My Chapter")
assert result.chapter_label == "My Chapter"
def test_required_sections_count():
"""Ensure REQUIRED_SECTIONS matches the 8 sections in the template."""
assert len(REQUIRED_SECTIONS) == 8