anderson-ufrj commited on
Commit
de52c4a
·
1 Parent(s): d5b36b2

test(agents): update tests for refactored agents

Browse files

- Update test_zumbi.py to use InvestigatorAgent with new interface
- Update test_anita.py to use AnalystAgent with new interface
- Create test_tiradentes_reporter.py for ReporterAgent
- Fix all agent initialization parameters to match new pattern
- Update all message actions to use new naming convention
- Add tests for initialize() and shutdown() methods
- Update assertions to match new agent properties

This ensures test compatibility with the refactored agent architecture

tests/unit/agents/test_anita.py CHANGED
@@ -10,10 +10,10 @@ from unittest.mock import Mock, AsyncMock, patch, MagicMock
10
  from uuid import uuid4
11
 
12
  from src.agents.anita import (
13
- AnitaAgent,
14
  PatternResult,
15
  CorrelationResult,
16
- PatternAnalysisRequest,
17
  )
18
  from src.agents.deodoro import (
19
  AgentContext,
@@ -170,11 +170,10 @@ def anita_agent(mock_transparency_api, mock_spectral_analyzer):
170
  with patch("src.agents.anita.TransparencyAPIClient", return_value=mock_transparency_api), \
171
  patch("src.agents.anita.SpectralAnalyzer", return_value=mock_spectral_analyzer):
172
 
173
- agent = AnitaAgent(
174
- pattern_significance_threshold=0.7,
175
- correlation_threshold=0.6,
176
- max_analysis_depth=5,
177
- semantic_similarity_threshold=0.8
178
  )
179
  return agent
180
 
@@ -186,10 +185,9 @@ class TestAnitaAgent:
186
  def test_agent_initialization(self, anita_agent):
187
  """Test Anita agent initialization."""
188
  assert anita_agent.name == "Anita"
189
- assert anita_agent.pattern_significance_threshold == 0.7
190
- assert anita_agent.correlation_threshold == 0.6
191
- assert anita_agent.max_analysis_depth == 5
192
- assert anita_agent.semantic_similarity_threshold == 0.8
193
 
194
  # Check capabilities
195
  expected_capabilities = [
@@ -210,7 +208,7 @@ class TestAnitaAgent:
210
  message = AgentMessage(
211
  sender="investigator_agent",
212
  recipient="Anita",
213
- action="analyze_temporal_patterns",
214
  payload={
215
  "data_type": "expenses",
216
  "time_window": "2024-01-01:2024-06-30",
@@ -241,7 +239,7 @@ class TestAnitaAgent:
241
  message = AgentMessage(
242
  sender="analyst_agent",
243
  recipient="Anita",
244
- action="detect_correlations",
245
  payload={
246
  "variables": ["contract_values", "expense_amounts", "supplier_count"],
247
  "correlation_methods": ["pearson", "spearman", "mutual_information"],
@@ -278,7 +276,7 @@ class TestAnitaAgent:
278
  message = AgentMessage(
279
  sender="master_agent",
280
  recipient="Anita",
281
- action="semantic_route",
282
  payload={
283
  "queries": queries,
284
  "route_to_specialists": True,
@@ -305,7 +303,7 @@ class TestAnitaAgent:
305
  message = AgentMessage(
306
  sender="tiradentes_agent",
307
  recipient="Anita",
308
- action="analyze_supplier_concentration",
309
  payload={
310
  "analysis_scope": "ministry_level",
311
  "include_geographic_analysis": True,
@@ -335,7 +333,7 @@ class TestAnitaAgent:
335
  message = AgentMessage(
336
  sender="machado_agent",
337
  recipient="Anita",
338
- action="analyze_network_patterns",
339
  payload={
340
  "network_type": "supplier_ministry_relationships",
341
  "include_centrality_measures": True,
@@ -366,7 +364,7 @@ class TestAnitaAgent:
366
  message = AgentMessage(
367
  sender="investigator_agent",
368
  recipient="Anita",
369
- action="score_anomalies",
370
  payload={
371
  "data_points": [
372
  {"value": 1000000, "date": "2024-01-01", "entity": "supplier_a"},
@@ -398,7 +396,7 @@ class TestAnitaAgent:
398
  message = AgentMessage(
399
  sender="analyst_agent",
400
  recipient="Anita",
401
- action="forecast_trends",
402
  payload={
403
  "historical_data": {
404
  "2024-01": 1000000,
@@ -438,7 +436,7 @@ class TestAnitaAgent:
438
  message = AgentMessage(
439
  sender="quality_agent",
440
  recipient="Anita",
441
- action="analyze_temporal_patterns",
442
  payload={
443
  "data_type": "contracts",
444
  "significance_filter": True
@@ -460,7 +458,7 @@ class TestAnitaAgent:
460
  message = AgentMessage(
461
  sender="comprehensive_analyst",
462
  recipient="Anita",
463
- action="multi_dimensional_analysis",
464
  payload={
465
  "dimensions": ["temporal", "geographic", "categorical", "financial"],
466
  "interaction_analysis": True,
@@ -498,7 +496,7 @@ class TestAnitaAgent:
498
  message = AgentMessage(
499
  sender="test_agent",
500
  recipient="Anita",
501
- action="analyze_temporal_patterns",
502
  payload={"data_type": "contracts"}
503
  )
504
 
@@ -519,7 +517,7 @@ class TestAnitaAgent:
519
  AgentMessage(
520
  sender="concurrent_tester",
521
  recipient="Anita",
522
- action="analyze_temporal_patterns",
523
  payload={"data_type": f"data_stream_{i}"}
524
  )
525
  for i in range(3)
@@ -542,7 +540,7 @@ class TestAnitaAgent:
542
  message = AgentMessage(
543
  sender="cache_tester",
544
  recipient="Anita",
545
- action="analyze_temporal_patterns",
546
  payload={
547
  "data_type": "expenses",
548
  "cache_results": True,
 
10
  from uuid import uuid4
11
 
12
  from src.agents.anita import (
13
+ AnalystAgent,
14
  PatternResult,
15
  CorrelationResult,
16
+ AnalysisRequest,
17
  )
18
  from src.agents.deodoro import (
19
  AgentContext,
 
170
  with patch("src.agents.anita.TransparencyAPIClient", return_value=mock_transparency_api), \
171
  patch("src.agents.anita.SpectralAnalyzer", return_value=mock_spectral_analyzer):
172
 
173
+ agent = AnalystAgent(
174
+ min_correlation_threshold=0.3,
175
+ significance_threshold=0.05,
176
+ trend_detection_window=6
 
177
  )
178
  return agent
179
 
 
185
  def test_agent_initialization(self, anita_agent):
186
  """Test Anita agent initialization."""
187
  assert anita_agent.name == "Anita"
188
+ assert anita_agent.correlation_threshold == 0.3
189
+ assert anita_agent.significance_threshold == 0.05
190
+ assert anita_agent.trend_window == 6
 
191
 
192
  # Check capabilities
193
  expected_capabilities = [
 
208
  message = AgentMessage(
209
  sender="investigator_agent",
210
  recipient="Anita",
211
+ action="analyze",
212
  payload={
213
  "data_type": "expenses",
214
  "time_window": "2024-01-01:2024-06-30",
 
239
  message = AgentMessage(
240
  sender="analyst_agent",
241
  recipient="Anita",
242
+ action="analyze",
243
  payload={
244
  "variables": ["contract_values", "expense_amounts", "supplier_count"],
245
  "correlation_methods": ["pearson", "spearman", "mutual_information"],
 
276
  message = AgentMessage(
277
  sender="master_agent",
278
  recipient="Anita",
279
+ action="analyze",
280
  payload={
281
  "queries": queries,
282
  "route_to_specialists": True,
 
303
  message = AgentMessage(
304
  sender="tiradentes_agent",
305
  recipient="Anita",
306
+ action="analyze",
307
  payload={
308
  "analysis_scope": "ministry_level",
309
  "include_geographic_analysis": True,
 
333
  message = AgentMessage(
334
  sender="machado_agent",
335
  recipient="Anita",
336
+ action="analyze",
337
  payload={
338
  "network_type": "supplier_ministry_relationships",
339
  "include_centrality_measures": True,
 
364
  message = AgentMessage(
365
  sender="investigator_agent",
366
  recipient="Anita",
367
+ action="analyze",
368
  payload={
369
  "data_points": [
370
  {"value": 1000000, "date": "2024-01-01", "entity": "supplier_a"},
 
396
  message = AgentMessage(
397
  sender="analyst_agent",
398
  recipient="Anita",
399
+ action="analyze",
400
  payload={
401
  "historical_data": {
402
  "2024-01": 1000000,
 
436
  message = AgentMessage(
437
  sender="quality_agent",
438
  recipient="Anita",
439
+ action="analyze",
440
  payload={
441
  "data_type": "contracts",
442
  "significance_filter": True
 
458
  message = AgentMessage(
459
  sender="comprehensive_analyst",
460
  recipient="Anita",
461
+ action="analyze",
462
  payload={
463
  "dimensions": ["temporal", "geographic", "categorical", "financial"],
464
  "interaction_analysis": True,
 
496
  message = AgentMessage(
497
  sender="test_agent",
498
  recipient="Anita",
499
+ action="analyze",
500
  payload={"data_type": "contracts"}
501
  )
502
 
 
517
  AgentMessage(
518
  sender="concurrent_tester",
519
  recipient="Anita",
520
+ action="analyze",
521
  payload={"data_type": f"data_stream_{i}"}
522
  )
523
  for i in range(3)
 
540
  message = AgentMessage(
541
  sender="cache_tester",
542
  recipient="Anita",
543
+ action="analyze",
544
  payload={
545
  "data_type": "expenses",
546
  "cache_results": True,
tests/unit/agents/test_tiradentes.py CHANGED
@@ -9,10 +9,10 @@ from unittest.mock import Mock, AsyncMock, patch, MagicMock
9
  from uuid import uuid4
10
 
11
  from src.agents.tiradentes import (
12
- TiradentesAgent,
13
- InvestigationRequest,
14
- AnomalyReport,
15
- CorruptionIndicator,
16
  )
17
  from src.agents.deodoro import (
18
  AgentContext,
@@ -138,33 +138,31 @@ def agent_context():
138
 
139
 
140
  @pytest.fixture
141
- def tiradentes_agent(mock_data_service, mock_ai_service):
142
- """Create Tiradentes agent with mocked dependencies."""
143
- with patch("src.agents.tiradentes.DataService", return_value=mock_data_service), \
144
- patch("src.agents.tiradentes.AIService", return_value=mock_ai_service):
145
-
146
- agent = TiradentesAgent(
147
- anomaly_threshold=0.7,
148
- correlation_threshold=0.8,
149
- max_investigation_depth=3
150
- )
151
- return agent
152
 
153
 
154
  class TestTiradentesAgent:
155
- """Test suite for Tiradentes (Investigation Agent)."""
156
 
157
  @pytest.mark.unit
158
  def test_agent_initialization(self, tiradentes_agent):
159
  """Test Tiradentes agent initialization."""
160
  assert tiradentes_agent.name == "Tiradentes"
161
- assert tiradentes_agent.anomaly_threshold == 0.7
162
- assert tiradentes_agent.correlation_threshold == 0.8
163
- assert tiradentes_agent.max_investigation_depth == 3
164
 
165
  # Check capabilities
166
  expected_capabilities = [
167
- "anomaly_detection",
 
 
 
168
  "corruption_analysis",
169
  "investigation_planning",
170
  "pattern_recognition",
 
9
  from uuid import uuid4
10
 
11
  from src.agents.tiradentes import (
12
+ ReporterAgent,
13
+ ReportRequest,
14
+ ReportType,
15
+ ReportFormat,
16
  )
17
  from src.agents.deodoro import (
18
  AgentContext,
 
138
 
139
 
140
  @pytest.fixture
141
+ def tiradentes_agent():
142
+ """Create Tiradentes agent (ReporterAgent)."""
143
+ agent = ReporterAgent(
144
+ default_language="pt",
145
+ max_report_length=10000
146
+ )
147
+ return agent
 
 
 
 
148
 
149
 
150
  class TestTiradentesAgent:
151
+ """Test suite for Tiradentes (Reporter Agent)."""
152
 
153
  @pytest.mark.unit
154
  def test_agent_initialization(self, tiradentes_agent):
155
  """Test Tiradentes agent initialization."""
156
  assert tiradentes_agent.name == "Tiradentes"
157
+ assert tiradentes_agent.default_language == "pt"
158
+ assert tiradentes_agent.max_length == 10000
 
159
 
160
  # Check capabilities
161
  expected_capabilities = [
162
+ "investigation_report_generation",
163
+ "pattern_analysis_reporting",
164
+ "executive_summary_creation",
165
+ "multi_format_rendering",
166
  "corruption_analysis",
167
  "investigation_planning",
168
  "pattern_recognition",
tests/unit/agents/test_tiradentes_reporter.py ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Unit tests for Tiradentes Agent (ReporterAgent) - Report generation specialist.
3
+ Tests report generation, formatting, and multi-language support.
4
+ """
5
+
6
+ import pytest
7
+ from datetime import datetime
8
+ from unittest.mock import Mock, AsyncMock, patch, MagicMock
9
+
10
+ from src.agents.tiradentes import (
11
+ ReporterAgent,
12
+ ReportRequest,
13
+ ReportType,
14
+ ReportFormat,
15
+ )
16
+ from src.agents.deodoro import (
17
+ AgentContext,
18
+ AgentMessage,
19
+ AgentResponse,
20
+ AgentStatus,
21
+ )
22
+ from src.core.exceptions import AgentExecutionError
23
+
24
+
25
+ @pytest.fixture
26
+ def investigation_results():
27
+ """Sample investigation results from Zumbi agent."""
28
+ return {
29
+ "anomalies": [
30
+ {
31
+ "anomaly_type": "price_anomaly",
32
+ "severity": 0.85,
33
+ "confidence": 0.92,
34
+ "description": "Contract value 3.5x above market average",
35
+ "explanation": "Significant price deviation detected",
36
+ "evidence": {
37
+ "contract_id": "123/2024",
38
+ "value": 5000000.0,
39
+ "market_average": 1428571.0
40
+ },
41
+ "recommendations": [
42
+ "Review pricing justification",
43
+ "Compare with similar contracts"
44
+ ]
45
+ }
46
+ ],
47
+ "summary": {
48
+ "total_records": 100,
49
+ "anomalies_found": 3,
50
+ "investigation_id": "inv-123"
51
+ }
52
+ }
53
+
54
+
55
+ @pytest.fixture
56
+ def analysis_results():
57
+ """Sample analysis results from Anita agent."""
58
+ return {
59
+ "patterns": [
60
+ {
61
+ "pattern_type": "temporal",
62
+ "description": "End-of-year spending spike",
63
+ "significance": 0.78,
64
+ "confidence": 0.85,
65
+ "insights": ["Budget execution rush", "Possible inefficiency"],
66
+ "evidence": {
67
+ "period": "Q4 2023",
68
+ "increase_percentage": 145
69
+ }
70
+ }
71
+ ],
72
+ "correlations": [
73
+ {
74
+ "correlation_type": "vendor_concentration",
75
+ "variables": ["vendor_id", "contract_count"],
76
+ "correlation_coefficient": 0.82,
77
+ "significance_level": "high"
78
+ }
79
+ ]
80
+ }
81
+
82
+
83
+ @pytest.fixture
84
+ def agent_context():
85
+ """Create agent context for testing."""
86
+ return AgentContext(
87
+ investigation_id="test-report-123",
88
+ user_id="test_user",
89
+ session_id="test_session",
90
+ metadata={"purpose": "testing"}
91
+ )
92
+
93
+
94
+ @pytest.fixture
95
+ def tiradentes_agent():
96
+ """Create Tiradentes agent (ReporterAgent)."""
97
+ return ReporterAgent(
98
+ default_language="pt",
99
+ max_report_length=10000
100
+ )
101
+
102
+
103
+ class TestTiradentesReporterAgent:
104
+ """Test suite for Tiradentes (Reporter Agent)."""
105
+
106
+ @pytest.mark.unit
107
+ def test_agent_initialization(self, tiradentes_agent):
108
+ """Test Tiradentes agent initialization."""
109
+ assert tiradentes_agent.name == "Tiradentes"
110
+ assert tiradentes_agent.default_language == "pt"
111
+ assert tiradentes_agent.max_length == 10000
112
+
113
+ # Check capabilities
114
+ expected_capabilities = [
115
+ "investigation_report_generation",
116
+ "pattern_analysis_reporting",
117
+ "executive_summary_creation",
118
+ "multi_format_rendering"
119
+ ]
120
+
121
+ for capability in expected_capabilities:
122
+ assert capability in tiradentes_agent.capabilities
123
+
124
+ @pytest.mark.unit
125
+ async def test_initialize_and_shutdown(self, tiradentes_agent):
126
+ """Test agent lifecycle methods."""
127
+ await tiradentes_agent.initialize()
128
+ await tiradentes_agent.shutdown()
129
+ # Should complete without errors
130
+
131
+ @pytest.mark.unit
132
+ async def test_generate_investigation_report(
133
+ self, tiradentes_agent, agent_context, investigation_results
134
+ ):
135
+ """Test generation of investigation report."""
136
+ message = AgentMessage(
137
+ sender="test",
138
+ recipient="Tiradentes",
139
+ action="generate_report",
140
+ payload={
141
+ "report_type": "investigation_report",
142
+ "format": "markdown",
143
+ "investigation_results": investigation_results,
144
+ "target_audience": "technical",
145
+ "include_visualizations": True
146
+ }
147
+ )
148
+
149
+ response = await tiradentes_agent.process(message, agent_context)
150
+
151
+ assert isinstance(response, AgentResponse)
152
+ assert response.agent_name == "Tiradentes"
153
+ assert response.status == AgentStatus.COMPLETED
154
+ assert "content" in response.result
155
+ assert "anomalies" in response.result["content"].lower()
156
+
157
+ @pytest.mark.unit
158
+ async def test_generate_analysis_report(
159
+ self, tiradentes_agent, agent_context, analysis_results
160
+ ):
161
+ """Test generation of analysis report."""
162
+ message = AgentMessage(
163
+ sender="test",
164
+ recipient="Tiradentes",
165
+ action="generate_report",
166
+ payload={
167
+ "report_type": "analysis_report",
168
+ "format": "markdown",
169
+ "analysis_results": analysis_results,
170
+ "language": "pt",
171
+ "detailed_findings": True
172
+ }
173
+ )
174
+
175
+ response = await tiradentes_agent.process(message, agent_context)
176
+
177
+ assert response.status == AgentStatus.COMPLETED
178
+ assert "patterns" in response.result["content"].lower()
179
+
180
+ @pytest.mark.unit
181
+ async def test_generate_executive_summary(
182
+ self, tiradentes_agent, agent_context, investigation_results, analysis_results
183
+ ):
184
+ """Test generation of executive summary."""
185
+ message = AgentMessage(
186
+ sender="test",
187
+ recipient="Tiradentes",
188
+ action="generate_report",
189
+ payload={
190
+ "report_type": "executive_summary",
191
+ "format": "executive_summary",
192
+ "investigation_results": investigation_results,
193
+ "analysis_results": analysis_results,
194
+ "target_audience": "executive"
195
+ }
196
+ )
197
+
198
+ response = await tiradentes_agent.process(message, agent_context)
199
+
200
+ assert response.status == AgentStatus.COMPLETED
201
+ # Executive summary should be concise
202
+ assert len(response.result["content"]) < 5000
203
+
204
+ @pytest.mark.unit
205
+ async def test_invalid_action(self, tiradentes_agent, agent_context):
206
+ """Test handling of invalid action."""
207
+ message = AgentMessage(
208
+ sender="test",
209
+ recipient="Tiradentes",
210
+ action="invalid_action",
211
+ payload={}
212
+ )
213
+
214
+ response = await tiradentes_agent.process(message, agent_context)
215
+
216
+ assert response.status == AgentStatus.ERROR
217
+ assert "Unsupported action" in response.error
218
+
219
+ @pytest.mark.unit
220
+ async def test_missing_data_error(self, tiradentes_agent, agent_context):
221
+ """Test error when no data provided."""
222
+ message = AgentMessage(
223
+ sender="test",
224
+ recipient="Tiradentes",
225
+ action="generate_report",
226
+ payload={
227
+ "report_type": "investigation_report",
228
+ "format": "markdown"
229
+ # Missing investigation_results and analysis_results
230
+ }
231
+ )
232
+
233
+ response = await tiradentes_agent.process(message, agent_context)
234
+
235
+ assert response.status == AgentStatus.ERROR
236
+ assert "No data provided" in response.error
237
+
238
+ @pytest.mark.unit
239
+ async def test_multi_language_support(
240
+ self, tiradentes_agent, agent_context, investigation_results
241
+ ):
242
+ """Test report generation in different languages."""
243
+ languages = ["pt", "en"]
244
+
245
+ for lang in languages:
246
+ message = AgentMessage(
247
+ sender="test",
248
+ recipient="Tiradentes",
249
+ action="generate_report",
250
+ payload={
251
+ "report_type": "investigation_report",
252
+ "format": "markdown",
253
+ "investigation_results": investigation_results,
254
+ "language": lang
255
+ }
256
+ )
257
+
258
+ response = await tiradentes_agent.process(message, agent_context)
259
+
260
+ assert response.status == AgentStatus.COMPLETED
261
+ assert response.result["metadata"]["language"] == lang
262
+
263
+ @pytest.mark.unit
264
+ async def test_report_format_rendering(
265
+ self, tiradentes_agent, agent_context, investigation_results
266
+ ):
267
+ """Test different report format rendering."""
268
+ formats = ["markdown", "html", "json"]
269
+
270
+ for fmt in formats:
271
+ message = AgentMessage(
272
+ sender="test",
273
+ recipient="Tiradentes",
274
+ action="generate_report",
275
+ payload={
276
+ "report_type": "investigation_report",
277
+ "format": fmt,
278
+ "investigation_results": investigation_results
279
+ }
280
+ )
281
+
282
+ response = await tiradentes_agent.process(message, agent_context)
283
+
284
+ assert response.status == AgentStatus.COMPLETED
285
+ assert response.result["metadata"]["format"] == fmt
tests/unit/agents/test_zumbi.py CHANGED
@@ -1,28 +1,92 @@
1
  """
2
- Unit tests for Zumbi Agent - Resistance and freedom analysis specialist.
3
  """
4
 
5
  import pytest
6
- from unittest.mock import AsyncMock
7
- from src.agents.zumbi import ZumbiAgent
8
- from src.agents.deodoro import AgentContext, AgentMessage, AgentStatus
9
 
10
  @pytest.fixture
11
  def zumbi_agent():
12
- return ZumbiAgent()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
  class TestZumbiAgent:
15
  @pytest.mark.unit
16
  def test_agent_initialization(self, zumbi_agent):
 
17
  assert zumbi_agent.name == "Zumbi"
18
- assert "resistance_analysis" in zumbi_agent.capabilities
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  @pytest.mark.unit
21
- async def test_resistance_analysis(self, zumbi_agent):
22
- context = AgentContext(investigation_id="resistance-test")
 
23
  message = AgentMessage(
24
- sender="test", recipient="Zumbi", action="analyze_resistance_patterns",
25
- payload={"movement_id": "social_movement_001"}
 
 
26
  )
 
27
  response = await zumbi_agent.process(message, context)
28
- assert response.status == AgentStatus.COMPLETED
 
 
 
1
  """
2
+ Unit tests for Zumbi Agent (InvestigatorAgent) - Anomaly detection specialist.
3
  """
4
 
5
  import pytest
6
+ from unittest.mock import AsyncMock, patch, MagicMock
7
+ from src.agents.zumbi import InvestigatorAgent
8
+ from src.agents.deodoro import AgentContext, AgentMessage, AgentResponse, AgentStatus
9
 
10
  @pytest.fixture
11
  def zumbi_agent():
12
+ """Create an InvestigatorAgent instance for testing."""
13
+ return InvestigatorAgent(
14
+ price_anomaly_threshold=2.5,
15
+ concentration_threshold=0.7,
16
+ duplicate_similarity_threshold=0.85
17
+ )
18
+
19
+ @pytest.fixture
20
+ def mock_transparency_client():
21
+ """Mock TransparencyAPIClient."""
22
+ client = AsyncMock()
23
+ client.search_contracts.return_value = [
24
+ {
25
+ "numeroContratoCompra": "123/2024",
26
+ "valorTotalCompra": 100000.0,
27
+ "dataPublicacaoContrato": "01/01/2024",
28
+ "orgaoEntidade": {"nome": "Ministério Teste"},
29
+ "fornecedor": {"nome": "Empresa ABC", "cnpj": "12345678901234"}
30
+ }
31
+ ]
32
+ return client
33
 
34
  class TestZumbiAgent:
35
  @pytest.mark.unit
36
  def test_agent_initialization(self, zumbi_agent):
37
+ """Test that the agent is properly initialized."""
38
  assert zumbi_agent.name == "Zumbi"
39
+ assert "price_anomaly_detection" in zumbi_agent.capabilities
40
+ assert "spectral_analysis" in zumbi_agent.capabilities
41
+ assert zumbi_agent.price_threshold == 2.5
42
+ assert zumbi_agent.concentration_threshold == 0.7
43
+
44
+ @pytest.mark.unit
45
+ async def test_initialize(self, zumbi_agent):
46
+ """Test agent initialization method."""
47
+ await zumbi_agent.initialize()
48
+ # Should complete without errors
49
+
50
+ @pytest.mark.unit
51
+ async def test_shutdown(self, zumbi_agent):
52
+ """Test agent shutdown method."""
53
+ await zumbi_agent.shutdown()
54
+ # Should complete without errors
55
+
56
+ @pytest.mark.unit
57
+ async def test_process_investigation(self, zumbi_agent, mock_transparency_client):
58
+ """Test processing an investigation request."""
59
+ with patch('src.agents.zumbi.TransparencyAPIClient', return_value=mock_transparency_client):
60
+ context = AgentContext(investigation_id="test-123")
61
+ message = AgentMessage(
62
+ sender="test",
63
+ recipient="Zumbi",
64
+ action="investigate",
65
+ payload={
66
+ "query": "contratos suspeitos",
67
+ "max_records": 10
68
+ }
69
+ )
70
+
71
+ response = await zumbi_agent.process(message, context)
72
+
73
+ assert isinstance(response, AgentResponse)
74
+ assert response.agent_name == "Zumbi"
75
+ assert response.status == AgentStatus.COMPLETED
76
+ assert "anomalies" in response.result
77
 
78
  @pytest.mark.unit
79
+ async def test_process_invalid_action(self, zumbi_agent):
80
+ """Test processing with invalid action."""
81
+ context = AgentContext(investigation_id="test-123")
82
  message = AgentMessage(
83
+ sender="test",
84
+ recipient="Zumbi",
85
+ action="invalid_action",
86
+ payload={}
87
  )
88
+
89
  response = await zumbi_agent.process(message, context)
90
+
91
+ assert response.status == AgentStatus.ERROR
92
+ assert "Unsupported action" in response.error