Skip to content

Commit e2d4731

Browse files
author
Alex Lavaee
committed
test: add integration test for agent lifecycle
- Verifies agent created once and ID stored - Confirms subsequent calls reuse agent by ID - Validates context manager cleanup (balanced enter/exit) - Ensures no resource leaks across multiple invocations
1 parent f0a2122 commit e2d4731

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

tests/test_tools_bing_search.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,3 +359,97 @@ def mock_factory(agent_id=None):
359359
assert calls[1] == "test-agent-123"
360360
# Third call retrieves by ID
361361
assert calls[2] == "test-agent-123"
362+
363+
364+
@pytest.mark.asyncio
365+
@patch.dict(
366+
"os.environ",
367+
{
368+
"BING_SUBSCRIPTION_KEY": "test_api_key",
369+
"AZURE_OPENAI_ENDPOINT": "https://test.openai.azure.com",
370+
"AZURE_OPENAI_API_KEY": "test_key",
371+
},
372+
clear=False,
373+
)
374+
async def test_web_search_full_lifecycle():
375+
"""
376+
Integration test verifying complete agent lifecycle.
377+
378+
Tests:
379+
- Agent created on first call with proper context manager cleanup
380+
- Agent ID stored at module level
381+
- Subsequent calls retrieve agent by ID with new context managers
382+
- Each context manager properly cleaned up (enters/exits balanced)
383+
"""
384+
import spec_to_agents.tools.bing_search as bing_search_module
385+
from spec_to_agents.tools.bing_search import web_search
386+
387+
# Verify starting with no agent ID
388+
assert bing_search_module._web_search_agent_id is None
389+
390+
with (
391+
patch("spec_to_agents.tools.bing_search.create_agent_client") as mock_client_factory,
392+
patch("spec_to_agents.tools.bing_search.HostedWebSearchTool"),
393+
):
394+
mock_client = Mock()
395+
mock_agent = Mock()
396+
397+
# Track context manager calls to verify cleanup
398+
enter_count = 0
399+
exit_count = 0
400+
401+
async def mock_enter(self):
402+
nonlocal enter_count
403+
enter_count += 1
404+
return mock_client
405+
406+
async def mock_exit(self, *args):
407+
nonlocal exit_count
408+
exit_count += 1
409+
return
410+
411+
mock_client.__aenter__ = mock_enter
412+
mock_client.__aexit__ = mock_exit
413+
414+
# Mock agent with ID
415+
mock_agent.id = "persistent-agent-456"
416+
417+
response1 = Mock()
418+
response1.text = "First result"
419+
response2 = Mock()
420+
response2.text = "Second result"
421+
response3 = Mock()
422+
response3.text = "Third result"
423+
424+
mock_agent.run = AsyncMock(side_effect=[response1, response2, response3])
425+
mock_client.create_agent.return_value = mock_agent
426+
mock_client.run = AsyncMock(side_effect=[response1, response2, response3])
427+
mock_client_factory.return_value = mock_client
428+
429+
# First call - creates agent
430+
result1 = await web_search("query 1")
431+
assert result1 == "First result"
432+
assert bing_search_module._web_search_agent_id == "persistent-agent-456"
433+
# One context manager used for creation, one for run
434+
assert enter_count == 2 # Once for creation, once for run
435+
assert exit_count == 2
436+
437+
# Second call - retrieves by ID
438+
result2 = await web_search("query 2")
439+
assert result2 == "Second result"
440+
# Still same agent ID
441+
assert bing_search_module._web_search_agent_id == "persistent-agent-456"
442+
# Additional context manager for retrieval
443+
assert enter_count == 3 # One more for run
444+
assert exit_count == 3
445+
446+
# Third call - retrieves by ID again
447+
result3 = await web_search("query 3")
448+
assert result3 == "Third result"
449+
assert bing_search_module._web_search_agent_id == "persistent-agent-456"
450+
# Another context manager for retrieval
451+
assert enter_count == 4
452+
assert exit_count == 4
453+
454+
# Verify context managers are balanced (proper cleanup)
455+
assert enter_count == exit_count

0 commit comments

Comments
 (0)