Spaces:
Running
Running
| """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 | |