Merge: fix-testing - Add comprehensive tests
This commit is contained in:
@@ -0,0 +1,291 @@
|
||||
"""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"])
|
||||
Reference in New Issue
Block a user