|
| 1 | +"""Tests for workflow patterns core module. |
| 2 | +
|
| 3 | +Module: workflow_patterns/core.py (76 lines) |
| 4 | +""" |
| 5 | + |
| 6 | +import pytest |
| 7 | +from pydantic import ValidationError |
| 8 | + |
| 9 | +from empathy_os.workflow_patterns.core import ( |
| 10 | + PatternCategory, |
| 11 | + WorkflowComplexity, |
| 12 | + CodeSection, |
| 13 | + WorkflowPattern, |
| 14 | +) |
| 15 | + |
| 16 | + |
| 17 | +# ============================================================================ |
| 18 | +# PatternCategory Enum Tests |
| 19 | +# ============================================================================ |
| 20 | + |
| 21 | + |
| 22 | +@pytest.mark.unit |
| 23 | +class TestPatternCategory: |
| 24 | + """Test suite for PatternCategory enum.""" |
| 25 | + |
| 26 | + def test_enum_values_exist(self): |
| 27 | + """Test that all category values exist.""" |
| 28 | + assert PatternCategory.STRUCTURAL.value == "structural" |
| 29 | + assert PatternCategory.TIER.value == "tier" |
| 30 | + assert PatternCategory.INTEGRATION.value == "integration" |
| 31 | + assert PatternCategory.OUTPUT.value == "output" |
| 32 | + assert PatternCategory.BEHAVIOR.value == "behavior" |
| 33 | + |
| 34 | + def test_enum_count(self): |
| 35 | + """Test that enum has exactly 5 categories.""" |
| 36 | + assert len(list(PatternCategory)) == 5 |
| 37 | + |
| 38 | + |
| 39 | +# ============================================================================ |
| 40 | +# WorkflowComplexity Enum Tests |
| 41 | +# ============================================================================ |
| 42 | + |
| 43 | + |
| 44 | +@pytest.mark.unit |
| 45 | +class TestWorkflowComplexity: |
| 46 | + """Test suite for WorkflowComplexity enum.""" |
| 47 | + |
| 48 | + def test_enum_values_exist(self): |
| 49 | + """Test that all complexity values exist.""" |
| 50 | + assert WorkflowComplexity.SIMPLE.value == "simple" |
| 51 | + assert WorkflowComplexity.MODERATE.value == "moderate" |
| 52 | + assert WorkflowComplexity.COMPLEX.value == "complex" |
| 53 | + |
| 54 | + def test_enum_count(self): |
| 55 | + """Test that enum has exactly 3 complexity levels.""" |
| 56 | + assert len(list(WorkflowComplexity)) == 3 |
| 57 | + |
| 58 | + |
| 59 | +# ============================================================================ |
| 60 | +# CodeSection Dataclass Tests |
| 61 | +# ============================================================================ |
| 62 | + |
| 63 | + |
| 64 | +@pytest.mark.unit |
| 65 | +class TestCodeSection: |
| 66 | + """Test suite for CodeSection dataclass.""" |
| 67 | + |
| 68 | + def test_create_code_section(self): |
| 69 | + """Test creating CodeSection with required fields.""" |
| 70 | + # When |
| 71 | + section = CodeSection(location="imports", code="import os") |
| 72 | + |
| 73 | + # Then |
| 74 | + assert section.location == "imports" |
| 75 | + assert section.code == "import os" |
| 76 | + assert section.priority == 0 # Default |
| 77 | + |
| 78 | + def test_create_code_section_with_priority(self): |
| 79 | + """Test creating CodeSection with custom priority.""" |
| 80 | + # When |
| 81 | + section = CodeSection(location="methods", code="def test():\n pass", priority=10) |
| 82 | + |
| 83 | + # Then |
| 84 | + assert section.location == "methods" |
| 85 | + assert section.code == "def test():\n pass" |
| 86 | + assert section.priority == 10 |
| 87 | + |
| 88 | + |
| 89 | +# ============================================================================ |
| 90 | +# WorkflowPattern Pydantic Model Tests |
| 91 | +# ============================================================================ |
| 92 | + |
| 93 | + |
| 94 | +@pytest.mark.unit |
| 95 | +class TestWorkflowPattern: |
| 96 | + """Test suite for WorkflowPattern Pydantic model.""" |
| 97 | + |
| 98 | + |
| 99 | + def test_create_pattern_with_all_fields(self): |
| 100 | + """Test creating WorkflowPattern with all fields.""" |
| 101 | + # When |
| 102 | + pattern = WorkflowPattern( |
| 103 | + id="full_pattern", |
| 104 | + name="Full Pattern", |
| 105 | + category=PatternCategory.TIER, |
| 106 | + description="Full description", |
| 107 | + complexity=WorkflowComplexity.COMPLEX, |
| 108 | + use_cases=["use_case_1", "use_case_2"], |
| 109 | + examples=["example_1"], |
| 110 | + conflicts_with=["pattern_x"], |
| 111 | + requires=["pattern_y"], |
| 112 | + risk_weight=3.5, |
| 113 | + ) |
| 114 | + |
| 115 | + # Then |
| 116 | + assert pattern.id == "full_pattern" |
| 117 | + assert pattern.use_cases == ["use_case_1", "use_case_2"] |
| 118 | + assert pattern.examples == ["example_1"] |
| 119 | + assert pattern.conflicts_with == ["pattern_x"] |
| 120 | + assert pattern.requires == ["pattern_y"] |
| 121 | + assert pattern.risk_weight == 3.5 |
| 122 | + |
| 123 | + def test_pattern_risk_weight_validation_min(self): |
| 124 | + """Test that risk_weight must be >= 0.0.""" |
| 125 | + # When/Then |
| 126 | + with pytest.raises(ValidationError): |
| 127 | + WorkflowPattern( |
| 128 | + id="test", |
| 129 | + name="Test", |
| 130 | + category=PatternCategory.STRUCTURAL, |
| 131 | + description="Test", |
| 132 | + complexity=WorkflowComplexity.SIMPLE, |
| 133 | + risk_weight=-1.0, # Invalid |
| 134 | + ) |
| 135 | + |
| 136 | + def test_pattern_risk_weight_validation_max(self): |
| 137 | + """Test that risk_weight must be <= 5.0.""" |
| 138 | + # When/Then |
| 139 | + with pytest.raises(ValidationError): |
| 140 | + WorkflowPattern( |
| 141 | + id="test", |
| 142 | + name="Test", |
| 143 | + category=PatternCategory.STRUCTURAL, |
| 144 | + description="Test", |
| 145 | + complexity=WorkflowComplexity.SIMPLE, |
| 146 | + risk_weight=6.0, # Invalid |
| 147 | + ) |
| 148 | + |
| 149 | + def test_pattern_generate_code_sections_not_implemented(self): |
| 150 | + """Test that generate_code_sections raises NotImplementedError.""" |
| 151 | + # Given |
| 152 | + pattern = WorkflowPattern( |
| 153 | + id="test", |
| 154 | + name="Test", |
| 155 | + category=PatternCategory.STRUCTURAL, |
| 156 | + description="Test", |
| 157 | + complexity=WorkflowComplexity.SIMPLE, |
| 158 | + ) |
| 159 | + |
| 160 | + # When/Then |
| 161 | + with pytest.raises(NotImplementedError, match="Subclasses must implement"): |
| 162 | + pattern.generate_code_sections({}) |
| 163 | + |
| 164 | + def test_pattern_config_uses_enum_values(self): |
| 165 | + """Test that Pydantic config uses enum values.""" |
| 166 | + # When |
| 167 | + pattern = WorkflowPattern( |
| 168 | + id="test", |
| 169 | + name="Test", |
| 170 | + category="structural", # String value, not enum |
| 171 | + description="Test", |
| 172 | + complexity="simple", # String value, not enum |
| 173 | + ) |
| 174 | + |
| 175 | + # Then - should convert to enums |
| 176 | + assert isinstance(pattern.category, (PatternCategory, str)) |
| 177 | + assert isinstance(pattern.complexity, (WorkflowComplexity, str)) |
0 commit comments