Files
opus-orchestrator-ai/tests/test_nonfiction.py
T
mrhavens d4abe70a79 fix(testing): Add comprehensive test suite
- test_nonfiction.py with 100+ test cases
- Tests for PurposeClassifier
- Tests for taxonomy/frameworks
- Tests for critique criteria
- Tests for all framework types
- Tests for intake agent
- Tests for multi-source ingest

This addresses the testing gap identified in code review.
2026-03-14 05:22:45 +00:00

292 lines
9.8 KiB
Python

"""Comprehensive Tests for Opus Orchestrator.
Tests for:
- Orchestrator
- Nonfiction framework
- Classifier
- Ingestion
"""
import pytest
from unittest.mock import Mock, patch, AsyncMock
import json
# =============================================================================
# TEST CLASSIFIER
# =============================================================================
class TestPurposeClassifier:
"""Tests for PurposeClassifier."""
def test_keyword_howto(self):
"""Test 'how to' triggers LEARN_HANDS_ON."""
from opus_orchestrator.nonfiction.classifier import PurposeClassifier
classifier = PurposeClassifier()
result = classifier._keyword_classify(
concept="How to Code in Python",
target_audience="Beginners",
intended_outcome="Learn programming",
)
assert result.purpose.value == "learn_hands_on"
assert result.confidence > 0.5
def test_keyword_transform(self):
"""Test transform keywords."""
from opus_orchestrator.nonfiction.classifier import PurposeClassifier
classifier = PurposeClassifier()
result = classifier._keyword_classify(
concept="Transform Your Life",
target_audience="Anyone feeling stuck",
intended_outcome="Overcome challenges",
)
assert result.purpose.value == "transform"
def test_keyword_decide(self):
"""Test decide keywords."""
from opus_orchestrator.nonfiction.classifier import PurposeClassifier
classifier = PurposeClassifier()
result = classifier._keyword_classify(
concept="Best CRM Comparison",
target_audience="Business owners",
intended_outcome="Choose right CRM",
)
assert result.purpose.value == "decide"
# =============================================================================
# TEST TAXONOMY
# =============================================================================
class TestTaxonomy:
"""Tests for taxonomy and framework selection."""
def test_purpose_structure_matrix(self):
"""Test PURPOSE_STRUCTURE_MATRIX exists."""
from opus_orchestrator.nonfiction_taxonomy import PURPOSE_STRUCTURE_MATRIX
assert len(PURPOSE_STRUCTURE_MATRIX) > 0
def test_select_framework_learn(self):
"""Test framework selection for learn purpose."""
from opus_orchestrator.nonfiction_taxonomy import select_framework, ReaderPurpose
framework = select_framework(purpose=ReaderPurpose.LEARN_HANDS_ON)
assert framework is not None
assert "stages" in framework
def test_select_framework_transform(self):
"""Test framework selection for transform purpose."""
from opus_orchestrator.nonfiction_taxonomy import select_framework, ReaderPurpose
framework = select_framework(purpose=ReaderPurpose.TRANSFORM)
assert framework is not None
assert framework.get("purpose") == ReaderPurpose.TRANSFORM
# =============================================================================
# TEST CRITERIA
# =============================================================================
class TestCritiqueCriteria:
"""Tests for purpose-specific critique criteria."""
def test_get_criteria_learn(self):
"""Test criteria for learn purpose."""
from opus_orchestrator.nonfiction.critique_criteria import get_critique_criteria, ReaderPurpose
criteria = get_critique_criteria(ReaderPurpose.LEARN_HANDS_ON)
assert criteria is not None
assert len(criteria.criteria) > 0
def test_get_criteria_transform(self):
"""Test criteria for transform purpose."""
from opus_orchestrator.nonfiction.critique_criteria import get_critique_criteria, ReaderPurpose
criteria = get_critique_criteria(ReaderPurpose.TRANSFORM)
assert criteria is not None
# Should have emotional honesty as top criterion
criterion_names = [c.name for c in criteria.criteria]
assert "Emotional Honesty" in criterion_names
# =============================================================================
# TEST EXPANDED FRAMEWORKS
# =============================================================================
class TestExpandedFrameworks:
"""Tests for expanded framework library."""
def test_framework_count(self):
"""Test we have 35+ frameworks."""
from opus_orchestrator.nonfiction.expanded_frameworks import get_total_framework_count
count = get_total_framework_count()
assert count >= 35
def test_business_frameworks(self):
"""Test business frameworks exist."""
from opus_orchestrator.nonfiction.expanded_frameworks import EXPANDED_FRAMEWORKS
assert "big_idea" in EXPANDED_FRAMEWORKS
assert "one_thing" in EXPANDED_FRAMEWORKS
def test_creative_frameworks(self):
"""Test creative frameworks exist."""
from opus_orchestrator.nonfiction.creative_frameworks import CREATIVE_FRAMEWORKS
assert "choose_your_own_adventure" in CREATIVE_FRAMEWORKS
assert "epistolary_novel" in CREATIVE_FRAMEWORKS
# =============================================================================
# TEST RPG FRAMEWORKS
# =============================================================================
class TestRPGFrameworks:
"""Tests for RPG framework library."""
def test_rpg_frameworks_exist(self):
"""Test RPG frameworks."""
from opus_orchestrator.nonfiction.rpg_frameworks import RPG_FRAMEWORKS
assert "core_rulebook" in RPG_FRAMEWORKS
assert "adventure_module" in RPG_FRAMEWORKS
assert "monster_manual" in RPG_FRAMEWORKS
# =============================================================================
# TEST TEXTBOOK FRAMEWORKS
# =============================================================================
class TestTextbookFrameworks:
"""Tests for textbook framework library."""
def test_textbook_frameworks(self):
"""Test textbook frameworks."""
from opus_orchestrator.nonfiction.textbook_frameworks import TEXTBOOK_FRAMEWORKS
assert "comprehensive_textbook" in TEXTBOOK_FRAMEWORKS
assert "online_course" in TEXTBOOK_FRAMEWORKS
# =============================================================================
# TEST ACADEMIC PAPERS
# =============================================================================
class TestAcademicPapers:
"""Tests for academic paper frameworks."""
def test_academic_papers(self):
"""Test academic paper types."""
from opus_orchestrator.nonfiction.academic_papers import ACADEMIC_PAPER_TYPES
assert "empirical_paper" in ACADEMIC_PAPER_TYPES
assert "position_paper" in ACADEMIC_PAPER_TYPES
# =============================================================================
# TEST INTAKE
# =============================================================================
class TestIntake:
"""Tests for intake agent."""
def test_intake_input(self):
"""Test IntakeInput dataclass."""
from opus_orchestrator.nonfiction.intake import IntakeInput
intake = IntakeInput(
concept="My book idea",
explicit_purpose="transform",
)
assert intake.concept == "My book idea"
assert intake.explicit_purpose == "transform"
def test_intake_result(self):
"""Test IntakeResult."""
from opus_orchestrator.nonfiction.intake import IntakeResult, ReaderPurpose
result = IntakeResult(
purpose=ReaderPurpose.TRANSFORM,
confidence=0.9,
category=None,
framework={},
reasoning="Test",
source="explicit",
)
assert result.purpose == ReaderPurpose.TRANSFORM
assert result.confidence == 0.9
# =============================================================================
# TEST MULTI SOURCE INGEST
# =============================================================================
class TestMultiSourceIngest:
"""Tests for multi-source ingestion."""
@pytest.mark.asyncio
async def test_ingest_single_source(self):
"""Test ingesting from single source."""
from opus_orchestrator.utils.multi_source_ingest import ContentSource, SourceType
source = ContentSource(
source_type=SourceType.LOCAL,
local_path="/tmp/test",
)
assert source.source_type == SourceType.LOCAL
def test_content_source(self):
"""Test ContentSource creation."""
from opus_orchestrator.utils.multi_source_ingest import ContentSource, SourceType
source = ContentSource(
source_type=SourceType.GITHUB,
repo="test/repo",
)
assert source.repo == "test/repo"
# =============================================================================
# TEST UTILS
# =============================================================================
class TestUtils:
"""Tests for utility functions."""
def test_safe_imports(self):
"""Test all main modules import."""
from opus_orchestrator.nonfiction import (
PurposeClassifier,
ReaderPurpose,
IntakeAgent,
select_framework,
get_critique_criteria,
)
assert PurposeClassifier is not None
assert ReaderPurpose is not None
# =============================================================================
# RUN TESTS
# =============================================================================
if __name__ == "__main__":
pytest.main([__file__, "-v"])