You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_team_manager.py 5.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import os
  2. import json
  3. import pytest
  4. import asyncio
  5. from pathlib import Path
  6. from unittest.mock import AsyncMock, MagicMock, patch
  7. from autogenstudio.teammanager import TeamManager
  8. from autogenstudio.datamodel.types import TeamResult, EnvironmentVariable
  9. from autogen_core import CancellationToken
  10. @pytest.fixture
  11. def sample_config():
  12. """Create an actual team and dump its configuration"""
  13. from autogen_agentchat.agents import AssistantAgent
  14. from autogen_agentchat.teams import RoundRobinGroupChat
  15. from autogen_ext.models.openai import OpenAIChatCompletionClient
  16. from autogen_agentchat.conditions import TextMentionTermination
  17. agent = AssistantAgent(
  18. name="weather_agent",
  19. model_client=OpenAIChatCompletionClient(
  20. model="gpt-4o-mini",
  21. ),
  22. )
  23. agent_team = RoundRobinGroupChat(
  24. [agent],
  25. termination_condition=TextMentionTermination("TERMINATE")
  26. )
  27. # Dump component and return as dict
  28. config = agent_team.dump_component()
  29. return config.model_dump()
  30. @pytest.fixture
  31. def config_file(sample_config, tmp_path):
  32. """Create a temporary config file"""
  33. config_path = tmp_path / "test_config.json"
  34. with open(config_path, "w") as f:
  35. json.dump(sample_config, f)
  36. return config_path
  37. @pytest.fixture
  38. def config_dir(sample_config, tmp_path):
  39. """Create a temporary directory with multiple config files"""
  40. # Create JSON config
  41. json_path = tmp_path / "team1.json"
  42. with open(json_path, "w") as f:
  43. json.dump(sample_config, f)
  44. # Create YAML config from the same dict
  45. import yaml
  46. yaml_path = tmp_path / "team2.yaml"
  47. # Create a modified copy to verify we can distinguish between them
  48. yaml_config = sample_config.copy()
  49. yaml_config["label"] = "YamlTeam" # Change a field to identify this as the YAML version
  50. with open(yaml_path, "w") as f:
  51. yaml.dump(yaml_config, f)
  52. return tmp_path
  53. class TestTeamManager:
  54. @pytest.mark.asyncio
  55. async def test_load_from_file(self, config_file, sample_config):
  56. """Test loading configuration from a file"""
  57. config = await TeamManager.load_from_file(config_file)
  58. assert config == sample_config
  59. # Test file not found
  60. with pytest.raises(FileNotFoundError):
  61. await TeamManager.load_from_file("nonexistent_file.json")
  62. # Test unsupported format
  63. wrong_format = config_file.with_suffix(".txt")
  64. wrong_format.touch()
  65. with pytest.raises(ValueError, match="Unsupported file format"):
  66. await TeamManager.load_from_file(wrong_format)
  67. @pytest.mark.asyncio
  68. async def test_load_from_directory(self, config_dir):
  69. """Test loading all configurations from a directory"""
  70. configs = await TeamManager.load_from_directory(config_dir)
  71. assert len(configs) == 2
  72. # Check if at least one team has expected label
  73. team_labels = [config.get("label") for config in configs]
  74. assert "RoundRobinGroupChat" in team_labels or "YamlTeam" in team_labels
  75. @pytest.mark.asyncio
  76. async def test_create_team(self, sample_config):
  77. """Test creating a team from config"""
  78. team_manager = TeamManager()
  79. # Mock Team.load_component
  80. with patch("autogen_agentchat.base.Team.load_component") as mock_load:
  81. mock_team = MagicMock()
  82. mock_load.return_value = mock_team
  83. team = await team_manager._create_team(sample_config)
  84. assert team == mock_team
  85. mock_load.assert_called_once_with(sample_config)
  86. @pytest.mark.asyncio
  87. async def test_run_stream(self, sample_config):
  88. """Test streaming team execution results"""
  89. team_manager = TeamManager()
  90. # Mock _create_team and team.run_stream
  91. with patch.object(team_manager, "_create_team") as mock_create:
  92. mock_team = MagicMock()
  93. # Create some mock messages to stream
  94. mock_messages = [MagicMock(), MagicMock()]
  95. mock_result = MagicMock() # TaskResult from run
  96. mock_messages.append(mock_result) # Last message is the result
  97. # Set up the async generator for run_stream
  98. async def mock_run_stream(*args, **kwargs):
  99. for msg in mock_messages:
  100. yield msg
  101. mock_team.run_stream = mock_run_stream
  102. mock_create.return_value = mock_team
  103. # Call run_stream and collect results
  104. streamed_messages = []
  105. async for message in team_manager.run_stream(
  106. task="Test task",
  107. team_config=sample_config
  108. ):
  109. streamed_messages.append(message)
  110. # Verify the team was created
  111. mock_create.assert_called_once()
  112. # Check that we got the expected number of messages +1 for the TeamResult
  113. assert len(streamed_messages) == len(mock_messages)
  114. # Verify the last message is a TeamResult
  115. assert isinstance(streamed_messages[-1], type(mock_messages[-1]))