Mayank2027 commited on
Commit
0278fed
·
verified ·
1 Parent(s): 024ac9e

Delete conftest.py

Browse files
Files changed (1) hide show
  1. conftest.py +0 -398
conftest.py DELETED
@@ -1,398 +0,0 @@
1
- """
2
- conftest.py – Shared pytest fixtures and configuration.
3
- Place this in your tests/ directory or project root.
4
- """
5
-
6
- import pytest
7
- import asyncio
8
- import sys
9
- import os
10
- import json
11
- from unittest.mock import AsyncMock, MagicMock
12
- from datetime import datetime
13
-
14
- # Ensure project root is in path
15
- sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
16
-
17
- # Import all modules that need mocking
18
- from models import AgentState, PlanStep, TaskStatus, AgentMetrics, SessionMetrics, AgentMessage
19
- from agents import BaseAgent, ResearchAgent, SalesAgent, SupportAgent, DataAgent, CodeAgent, ContentAgent, CriticAgent, MetaAgent, AgentFactory
20
- from supervisor import SupervisorAgent
21
- from llm_client import LLMClient, LLMRouter
22
- from tools import ToolRegistry
23
- from metrics import metrics_collector, MetricsCollector
24
- from memory import memory_manager, MemoryManager
25
- from orchestrator import MultiAgentOrchestrator
26
-
27
-
28
- # =============================================================================
29
- # EVENT LOOP
30
- # =============================================================================
31
-
32
- @pytest.fixture(scope="session")
33
- def event_loop():
34
- """Create an instance of the default event loop for the test session."""
35
- loop = asyncio.get_event_loop_policy().new_event_loop()
36
- yield loop
37
- loop.close()
38
-
39
-
40
- # =============================================================================
41
- # MOCK PLAYWRIGHT PAGE
42
- # =============================================================================
43
-
44
- @pytest.fixture
45
- def mock_page():
46
- """
47
- Fully mocked Playwright page with all common methods.
48
- Returns realistic values for all async operations.
49
- """
50
- page = MagicMock()
51
-
52
- # Basic properties
53
- page.url = "https://example.com"
54
-
55
- # Async methods
56
- page.title = AsyncMock(return_value="Example Domain")
57
- page.evaluate = AsyncMock(return_value={"title": "Test", "textLength": 100, "url": "https://example.com"})
58
- page.screenshot = AsyncMock(return_value=b"fake_screenshot_bytes_12345")
59
- page.click = AsyncMock()
60
- page.fill = AsyncMock()
61
- page.goto = AsyncMock()
62
- page.select_option = AsyncMock()
63
- page.keyboard.press = AsyncMock()
64
- page.hover = AsyncMock()
65
- page.go_back = AsyncMock()
66
- page.wait_for_selector = AsyncMock()
67
- page.wait_for_navigation = AsyncMock()
68
- page.content = AsyncMock(return_value="<html><body><h1>Test</h1></body></html>")
69
- page.set_input_files = AsyncMock()
70
- page.set_viewport_size = AsyncMock()
71
- page.add_init_script = AsyncMock()
72
-
73
- # Context mock
74
- page.context = MagicMock()
75
- page.context.pages = [page]
76
- page.context.cookies = AsyncMock(return_value=[{"name": "test", "value": "val", "domain": ".example.com"}])
77
- page.context.add_cookies = AsyncMock()
78
- page.context.clear_cookies = AsyncMock()
79
- page.context.new_page = AsyncMock(return_value=page)
80
-
81
- # Locator mock
82
- page.locator = MagicMock()
83
- page.locator.return_value.first = MagicMock()
84
- page.locator.return_value.first.bounding_box = AsyncMock(return_value={"x": 0, "y": 0, "width": 100, "height": 50})
85
-
86
- # Download mock
87
- mock_download = MagicMock()
88
- mock_download.suggested_filename = "download.pdf"
89
- mock_download.save_as = AsyncMock()
90
- page.context.expect_download = AsyncMock()
91
- page.context.expect_download.return_value.__aenter__ = AsyncMock(return_value=MagicMock())
92
- page.context.expect_download.return_value.__aexit__ = AsyncMock(return_value=False)
93
-
94
- return page
95
-
96
-
97
- # =============================================================================
98
- # MOCK STATE
99
- # =============================================================================
100
-
101
- @pytest.fixture
102
- def mock_state():
103
- """Create a fresh AgentState for testing."""
104
- state = AgentState("Test task for unit testing")
105
- state.session_id = "test-session-123"
106
- return state
107
-
108
-
109
- @pytest.fixture
110
- def fresh_state():
111
- """Create a completely fresh AgentState with no defaults."""
112
- return AgentState("")
113
-
114
-
115
- # =============================================================================
116
- # MOCK TOOLS
117
- # =============================================================================
118
-
119
- @pytest.fixture
120
- def mock_tools(mock_page, mock_state):
121
- """Create a ToolRegistry with mocked page and state."""
122
- return ToolRegistry(mock_page, mock_state)
123
-
124
-
125
- @pytest.fixture
126
- def fresh_tools(mock_page, fresh_state):
127
- """Create a ToolRegistry with fresh state."""
128
- return ToolRegistry(mock_page, fresh_state)
129
-
130
-
131
- # =============================================================================
132
- # MOCK LLM RESPONSES
133
- # =============================================================================
134
-
135
- @pytest.fixture
136
- def mock_llm_navigate_response():
137
- """Standard navigate action response."""
138
- return json.dumps({
139
- "thought": "I need to navigate to the target website",
140
- "plan": [
141
- "Step 1: Navigate to target URL",
142
- "Step 2: Interact with page",
143
- "Step 3: Extract information",
144
- "Step 4: Done"
145
- ],
146
- "action": {
147
- "tool": "navigate",
148
- "params": {"url": "https://wikipedia.org"}
149
- }
150
- })
151
-
152
-
153
- @pytest.fixture
154
- def mock_llm_click_response():
155
- """Click action response."""
156
- return json.dumps({
157
- "thought": "Clicking the target element",
158
- "action": {
159
- "tool": "click",
160
- "params": {"selector": "#searchButton"}
161
- }
162
- })
163
-
164
-
165
- @pytest.fixture
166
- def mock_llm_fill_response():
167
- """Fill action response."""
168
- return json.dumps({
169
- "thought": "Filling the form field",
170
- "action": {
171
- "tool": "fill",
172
- "params": {"selector": "#searchInput", "value": "Artificial Intelligence"}
173
- }
174
- })
175
-
176
-
177
- @pytest.fixture
178
- def mock_llm_done_response():
179
- """Done action response."""
180
- return json.dumps({
181
- "thought": "Task is complete, all objectives achieved",
182
- "action": {
183
- "tool": "done",
184
- "params": {"result": "Successfully completed the assigned task with all requirements met"}
185
- }
186
- })
187
-
188
-
189
- @pytest.fixture
190
- def mock_llm_error_response():
191
- """Invalid/malformed response to test error handling."""
192
- return "This is not valid JSON {"
193
-
194
-
195
- @pytest.fixture
196
- def mock_llm_partial_json_response():
197
- """Response with JSON embedded in text."""
198
- return 'Some explanation text here {"thought": "extracted", "action": {"tool": "navigate", "params": {"url": "https://example.com"}}} more text after'
199
-
200
-
201
- # =============================================================================
202
- # MOCK SUPERVISOR PLANS
203
- # =============================================================================
204
-
205
- @pytest.fixture
206
- def mock_supervisor_single_step_plan():
207
- """Single step supervisor plan."""
208
- return json.dumps([
209
- {"step": 1, "agent": "Research", "task": "Search Wikipedia for AI", "depends_on": []}
210
- ])
211
-
212
-
213
- @pytest.fixture
214
- def mock_supervisor_multi_step_plan():
215
- """Multi-step supervisor plan with dependencies."""
216
- return json.dumps([
217
- {"step": 1, "agent": "Research", "task": "Search Wikipedia for AI", "depends_on": []},
218
- {"step": 2, "agent": "Research", "task": "Search Google for latest AI news", "depends_on": []},
219
- {"step": 3, "agent": "Content", "task": "Summarize findings into report", "depends_on": [1, 2]}
220
- ])
221
-
222
-
223
- @pytest.fixture
224
- def mock_supervisor_complex_plan():
225
- """Complex plan with multiple agents and dependencies."""
226
- return json.dumps([
227
- {"step": 1, "agent": "Research", "task": "Gather market data", "depends_on": []},
228
- {"step": 2, "agent": "Data", "task": "Analyze market trends", "depends_on": [1]},
229
- {"step": 3, "agent": "Sales", "task": "Create sales proposal", "depends_on": [2]},
230
- {"step": 4, "agent": "Content", "task": "Write executive summary", "depends_on": [2]},
231
- {"step": 5, "agent": "Code", "task": "Generate visualization charts", "depends_on": [2]},
232
- {"step": 6, "agent": "Content", "task": "Compile final report", "depends_on": [3, 4, 5]}
233
- ])
234
-
235
-
236
- # =============================================================================
237
- # MOCK AGENTS
238
- # =============================================================================
239
-
240
- @pytest.fixture
241
- def mock_research_agent(mock_tools, mock_state):
242
- """Create a mocked ResearchAgent."""
243
- agent = ResearchAgent(mock_tools, mock_state)
244
- agent.run = AsyncMock(return_value={
245
- "agent": "Research Agent",
246
- "result": "Research completed successfully",
247
- "history": [{"thought": "Found info", "action": {"tool": "navigate"}}],
248
- "steps": 3,
249
- "duration": 5.2,
250
- "errors": 0,
251
- "successes": 3
252
- })
253
- return agent
254
-
255
-
256
- @pytest.fixture
257
- def mock_content_agent(mock_tools, mock_state):
258
- """Create a mocked ContentAgent."""
259
- agent = ContentAgent(mock_tools, mock_state)
260
- agent.run = AsyncMock(return_value={
261
- "agent": "Content Agent",
262
- "result": "Summary generated",
263
- "history": [],
264
- "steps": 2,
265
- "duration": 3.1,
266
- "errors": 0,
267
- "successes": 2
268
- })
269
- return agent
270
-
271
-
272
- @pytest.fixture
273
- def mock_data_agent(mock_tools, mock_state):
274
- """Create a mocked DataAgent."""
275
- agent = DataAgent(mock_tools, mock_state)
276
- agent.run = AsyncMock(return_value={
277
- "agent": "Data Agent",
278
- "result": "Analysis complete",
279
- "history": [],
280
- "steps": 4,
281
- "duration": 8.5,
282
- "errors": 0,
283
- "successes": 4
284
- })
285
- return agent
286
-
287
-
288
- @pytest.fixture
289
- def mock_failing_agent(mock_tools, mock_state):
290
- """Create an agent that always fails."""
291
- agent = ResearchAgent(mock_tools, mock_state)
292
- agent.run = AsyncMock(side_effect=Exception("Simulated agent failure"))
293
- return agent
294
-
295
-
296
- # =============================================================================
297
- # MOCK ORCHESTRATOR
298
- # =============================================================================
299
-
300
- @pytest.fixture
301
- def mock_orchestrator(mock_page):
302
- """Create a mocked MultiAgentOrchestrator."""
303
- orch = MultiAgentOrchestrator(mock_page)
304
- orch.run = AsyncMock(return_value={
305
- "plan": [{"step": 1, "agent": "Research", "task": "Test"}],
306
- "agent_results": {1: {"result": "Done"}},
307
- "solution": "Test solution"
308
- })
309
- return orch
310
-
311
-
312
- # =============================================================================
313
- # CLEANUP FIXTURES
314
- # =============================================================================
315
-
316
- @pytest.fixture(autouse=True)
317
- def reset_metrics_collector():
318
- """Reset metrics collector before each test."""
319
- metrics_collector.sessions.clear()
320
- yield
321
- metrics_collector.sessions.clear()
322
-
323
-
324
- @pytest.fixture(autouse=True)
325
- def reset_llm_usage_stats():
326
- """Reset LLM usage stats before each test."""
327
- LLMRouter._usage_stats.clear()
328
- yield
329
-
330
-
331
- # =============================================================================
332
- # HELPER FUNCTIONS
333
- # =============================================================================
334
-
335
- def create_mock_llm_sequence(responses: list):
336
- """
337
- Helper to create a sequence of LLM responses for testing multi-step workflows.
338
-
339
- Usage:
340
- with patch.object(LLMClient, 'chat', new_callable=AsyncMock) as mock_chat:
341
- mock_chat.side_effect = create_mock_llm_sequence([
342
- mock_llm_navigate_response,
343
- mock_llm_click_response,
344
- mock_llm_done_response
345
- ])
346
- """
347
- async def mock_chat(*args, **kwargs):
348
- if not responses:
349
- return (json.dumps({"thought": "Default", "action": {"tool": "done", "params": {"result": "Default"}}}), {})
350
- response = responses.pop(0)
351
- if callable(response):
352
- response = response()
353
- return (response, {})
354
-
355
- return mock_chat
356
-
357
-
358
- def assert_valid_agent_result(result: dict):
359
- """Assert that an agent result has all required fields."""
360
- assert "agent" in result
361
- assert "result" in result
362
- assert "history" in result
363
- assert "steps" in result
364
- assert "duration" in result
365
- assert "errors" in result
366
- assert "successes" in result
367
- assert isinstance(result["history"], list)
368
- assert isinstance(result["steps"], int)
369
- assert result["steps"] >= 0
370
-
371
-
372
- def assert_valid_plan(plan: list):
373
- """Assert that a plan is valid."""
374
- assert isinstance(plan, list)
375
- for step in plan:
376
- assert isinstance(step, (dict, PlanStep))
377
- if isinstance(step, dict):
378
- assert "step" in step
379
- assert "agent" in step
380
- assert "task" in step
381
- else:
382
- assert step.step >= 1
383
- assert step.agent
384
- assert step.task
385
-
386
-
387
- # =============================================================================
388
- # CUSTOM MARKERS
389
- # =============================================================================
390
-
391
- def pytest_configure(config):
392
- """Register custom markers."""
393
- config.addinivalue_line("markers", "slow: marks tests as slow")
394
- config.addinivalue_line("markers", "integration: marks tests as integration tests")
395
- config.addinivalue_line("markers", "performance: marks tests as performance tests")
396
- config.addinivalue_line("markers", "unit: marks tests as unit tests")
397
- config.addinivalue_line("markers", "llm: marks tests that require LLM API calls")
398
- config.addinivalue_line("markers", "browser: marks tests that require browser automation")