From 4b97d9eee4eb5f5100e145e26e432cd03a36703a Mon Sep 17 00:00:00 2001 From: Weirui Kuang <39145382+rayrayraykk@users.noreply.github.com> Date: Thu, 11 Dec 2025 19:11:06 +0800 Subject: [PATCH] Remove ut for samples (#78) * remove ut for each sample * rm tests --- .../workflows/test_agent_deep_research.yml | 36 --- .github/workflows/test_browser_agent_test.yml | 46 ---- .../test_browser_use_fullstack_runtime.yml | 40 --- .../test_conversational_agents_chatbot.yml | 34 --- ...ts_chatbot_fullstack_runtime_webserver.yml | 36 --- .github/workflows/test_evaluation.yml | 36 --- .github/workflows/test_game.yml | 35 --- tests/agent_deep_research_test.py | 203 -------------- tests/browser_agent_test.py | 171 ------------ tests/browser_use_fullstack_runtime_test.py | 145 ---------- ...hatbot_fullstack_runtime_webserver_test.py | 61 ----- tests/conversational_agents_chatbot_test.py | 103 -------- tests/data_juicer_agent_test.py | 248 ------------------ tests/evaluation_test.py | 163 ------------ tests/game_test.py | 116 -------- 15 files changed, 1473 deletions(-) delete mode 100644 .github/workflows/test_agent_deep_research.yml delete mode 100644 .github/workflows/test_browser_agent_test.yml delete mode 100644 .github/workflows/test_browser_use_fullstack_runtime.yml delete mode 100644 .github/workflows/test_conversational_agents_chatbot.yml delete mode 100644 .github/workflows/test_conversational_agents_chatbot_fullstack_runtime_webserver.yml delete mode 100644 .github/workflows/test_evaluation.yml delete mode 100644 .github/workflows/test_game.yml delete mode 100644 tests/agent_deep_research_test.py delete mode 100644 tests/browser_agent_test.py delete mode 100644 tests/browser_use_fullstack_runtime_test.py delete mode 100644 tests/conversational_agents_chatbot_fullstack_runtime_webserver_test.py delete mode 100644 tests/conversational_agents_chatbot_test.py delete mode 100644 tests/data_juicer_agent_test.py delete mode 100644 tests/evaluation_test.py delete mode 100644 tests/game_test.py diff --git a/.github/workflows/test_agent_deep_research.yml b/.github/workflows/test_agent_deep_research.yml deleted file mode 100644 index 43c94c4..0000000 --- a/.github/workflows/test_agent_deep_research.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: deep_research_runtime_test -on: [push, pull_request] - -jobs: - test: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.10'] - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Debug directory structure - run: | - echo "Current directory: $(pwd)" - ls -la - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - cd deep_research/agent_deep_research - pip install --upgrade pip - pip install -r requirements.txt - pip install pytest pytest-asyncio pytest-mock - - - name: Run tests - env: - PYTHONPATH: ${{ github.workspace }}/deep_research/agent_deep_research - run: | - python -m pytest tests/agent_deep_research_test.py -v \ No newline at end of file diff --git a/.github/workflows/test_browser_agent_test.yml b/.github/workflows/test_browser_agent_test.yml deleted file mode 100644 index 3316dd2..0000000 --- a/.github/workflows/test_browser_agent_test.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: BrowserAgent Tests - -on: [push] - -jobs: - test: - name: Run Tests (Python ${{ matrix.python-version }}) - runs-on: ubuntu-latest - - strategy: - matrix: - python-version: - - "3.10" - - steps: - - name: Checkout Repository - uses: actions/checkout@v4 - - - name: Debug directory structure - run: | - # ✅ Show actual directory structure - echo "Current directory: $(pwd)" - ls -la - - - name: Setup Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python-version }} - cache: pip - - - name: Install Dependencies - run: | - cd browser_use/agent_browser - python -m pip install --upgrade pip - pip install pytest pytest-asyncio - pip install -r requirements.txt - - - name: Run Tests - env: - PYTHONPATH: ${{ github.workspace }}/browser_use/agent_browser - DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }} - run: | - # ✅ Ensure test-results directory exists - mkdir -p test-results - # ✅ Run tests with XML output - python -m pytest tests/browser_agent_test.py -v \ No newline at end of file diff --git a/.github/workflows/test_browser_use_fullstack_runtime.yml b/.github/workflows/test_browser_use_fullstack_runtime.yml deleted file mode 100644 index a23bab0..0000000 --- a/.github/workflows/test_browser_use_fullstack_runtime.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: browser_use_fullstack_runtime_test -on: [push] - -jobs: - test: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.10'] - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Debug directory structure - run: | - # ✅ Show actual directory structure - echo "Current directory: $(pwd)" - ls -la - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - # ✅ Use validated path from debug output - cd browser_use/browser_use_fullstack_runtime/backend - pip install pytest pytest-asyncio - python -m pip install --upgrade pip - pip install -r requirements.txt - - - name: Run tests - env: - DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }} - PYTHONPATH: ${{ github.workspace }}/browser_use/browser_use_fullstack_runtime/backend - run: | - # ✅ Use validated path from debug output - python -m pytest tests/browser_use_fullstack_runtime_test.py -v \ No newline at end of file diff --git a/.github/workflows/test_conversational_agents_chatbot.yml b/.github/workflows/test_conversational_agents_chatbot.yml deleted file mode 100644 index ac59f67..0000000 --- a/.github/workflows/test_conversational_agents_chatbot.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Conversational Agents Chatbot Test -on: [push] - -jobs: - test: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.10'] - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - # ✅ Use correct relative path - cd conversational_agents/chatbot - python -m pip install --upgrade pip - pip install pytest pytest-asyncio - pip install -r requirements.txt - - - name: Run tests - env: - PYTHONPATH: ${{ github.workspace }}/conversational_agents/chatbot - DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }} - run: | - # ✅ Use correct relative path - python -m pytest tests/conversational_agents_chatbot_test.py -v \ No newline at end of file diff --git a/.github/workflows/test_conversational_agents_chatbot_fullstack_runtime_webserver.yml b/.github/workflows/test_conversational_agents_chatbot_fullstack_runtime_webserver.yml deleted file mode 100644 index b7bb254..0000000 --- a/.github/workflows/test_conversational_agents_chatbot_fullstack_runtime_webserver.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: Flask API Runtime Test -on: [push] - -jobs: - test: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.10'] - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Debug directory structure - run: | - echo "Current directory: $(pwd)" - ls -la - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - cd conversational_agents/chatbot_fullstack_runtime/backend - pip install --upgrade pip - pip install -r requirements.txt - pip install pytest pytest-asyncio - - - name: Run tests - env: - PYTHONPATH: ${{ github.workspace }}/conversational_agents/chatbot_fullstack_runtime - run: | - python -m pytest tests/conversational_agents_chatbot_fullstack_runtime_webserver_test.py -v \ No newline at end of file diff --git a/.github/workflows/test_evaluation.yml b/.github/workflows/test_evaluation.yml deleted file mode 100644 index 99cee2c..0000000 --- a/.github/workflows/test_evaluation.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: ACE Benchmark Evaluation Test -on: [push] - -jobs: - test: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.10'] - - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Debug directory structure - run: | - echo "Current directory: $(pwd)" - ls -la - - - name: Setup Python - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - - name: Install dependencies - run: | - pip install --upgrade pip - pip install pytest pytest-asyncio pytest-mock - pip install agentscope ray - - - name: Run tests - env: - PYTHONPATH: ${{ env.GITHUB_WORKSPACE }}/evaluation/ace_bench - DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }} - run: | - python -m pytest tests/evaluation_test.py -v \ No newline at end of file diff --git a/.github/workflows/test_game.yml b/.github/workflows/test_game.yml deleted file mode 100644 index cd8292c..0000000 --- a/.github/workflows/test_game.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Run test_game.py - -on: [push] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Debug directory structure - run: | - # ✅ Show actual directory structure - echo "Current directory: $(pwd)" - ls -la - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.10" - - - name: Install dependencies - run: | - cd games/game_werewolves - pip install pytest pytest-asyncio - pip install -r requirements.txt - - - name: Run game_test.py - env: - DASHSCOPE_API_KEY: ${{ secrets.DASHSCOPE_API_KEY }} - PYTHONPATH: $GITHUB_WORKSPACE/games/game_werewolves - run: | - # ✅ Ensure correct working directory - PYTHONPATH=$GITHUB_WORKSPACE/games/game_werewolves python -m pytest tests/game_test.py -v \ No newline at end of file diff --git a/tests/agent_deep_research_test.py b/tests/agent_deep_research_test.py deleted file mode 100644 index f4aa9f8..0000000 --- a/tests/agent_deep_research_test.py +++ /dev/null @@ -1,203 +0,0 @@ -# -*- coding: utf-8 -*- -import os -import shutil -import tempfile -from unittest.mock import Mock, AsyncMock, patch, MagicMock - -import pytest -from agentscope.formatter import DashScopeChatFormatter -from agentscope.mcp import StdIOStatefulClient -from agentscope.memory import InMemoryMemory -from agentscope.message import Msg -from agentscope.model import DashScopeChatModel - -from deep_research.agent_deep_research.deep_research_agent import ( - DeepResearchAgent, -) -from deep_research.agent_deep_research.main import main - - -@pytest.fixture -def mock_env_vars(monkeypatch): - """Fixture to set required environment variables""" - monkeypatch.setenv("TAVILY_API_KEY", "test_tavily_key") - monkeypatch.setenv("DASHSCOPE_API_KEY", "test_dashscope_key") - return { - "TAVILY_API_KEY": "test_tavily_key", - "DASHSCOPE_API_KEY": "test_dashscope_key", - } - - -@pytest.fixture -def temp_working_dir(): - """Create a temporary working directory""" - temp_dir = tempfile.mkdtemp() - yield temp_dir - shutil.rmtree(temp_dir) - - -@pytest.fixture -def mock_tavily_client(): - """Create a mocked Tavily client""" - client = AsyncMock(spec=StdIOStatefulClient) - client.name = "tavily_mcp" - client.connect = AsyncMock() - client.close = AsyncMock() - return client - - -@pytest.fixture -def mock_formatter(): - """Create a mocked formatter""" - return Mock(spec=DashScopeChatFormatter) - - -@pytest.fixture -def mock_memory(): - """Create a mocked memory instance""" - return Mock(spec=InMemoryMemory) - - -@pytest.fixture -def mock_model(): - """Create a mocked model instance""" - model = Mock(spec=DashScopeChatModel) - model.call = AsyncMock(return_value=Mock(content="test response")) - return model - - -class TestDeepResearchAgent: - """Test suite for Deep Research Agent functionality""" - - def test_agent_initialization( - self, - mock_model, # pylint: disable=redefined-outer-name - mock_tavily_client, # pylint: disable=redefined-outer-name - temp_working_dir, # pylint: disable=redefined-outer-name - ): - """Test agent initialization with valid parameters""" - mock_loop = MagicMock() - mock_task = AsyncMock() - mock_loop.create_task = MagicMock(return_value=mock_task) - with patch("asyncio.get_running_loop", return_value=mock_loop): - agent = DeepResearchAgent( - name="Friday", - sys_prompt="You are a helpful assistant named Friday.", - model=mock_model, - formatter=DashScopeChatFormatter(), - memory=InMemoryMemory(), - search_mcp_client=mock_tavily_client, - tmp_file_storage_dir=temp_working_dir, - ) - - assert agent.name == "Friday" - assert agent.sys_prompt.startswith( - "You are a helpful assistant named Friday.", - ) - assert agent.tmp_file_storage_dir == temp_working_dir - assert os.path.exists(temp_working_dir) - - @pytest.mark.asyncio - async def test_main_function_success( - self, - mock_tavily_client, # pylint: disable=redefined-outer-name - temp_working_dir, # pylint: disable=redefined-outer-name - ): - """Test main function with successful execution""" - with patch( - "deep_research.agent_deep_research.main.StdIOStatefulClient", - return_value=mock_tavily_client, - ): - with patch( - "deep_research.agent_deep_research.main.DeepResearchAgent", - autospec=True, - ) as mock_agent_class: - mock_agent = AsyncMock() - mock_agent.return_value = Msg( - "Friday", - "Test response", - "assistant", - ) - mock_agent_class.return_value = mock_agent - - with patch("os.makedirs") as mock_makedirs: - with patch.dict( - os.environ, - {"AGENT_OPERATION_DIR": temp_working_dir}, - ): - test_query = "Test research question" - - await main(test_query) - - mock_makedirs.assert_called_once_with( - temp_working_dir, - exist_ok=True, - ) - mock_agent_class.assert_called_once() - - # ✅ Use assert_called_once() + manual argument check - mock_agent.assert_called_once() - call_arg = mock_agent.call_args[0][0] - assert call_arg.name == "Bob" - assert call_arg.content == "Test research question" - - @pytest.mark.asyncio - async def test_main_function_with_missing_env_vars(self): - """Test main function handles missing environment variables""" - with patch.dict(os.environ, clear=True): - with pytest.raises(Exception): - await main("Test query") - - @pytest.mark.asyncio - async def test_agent_cleanup( - self, - mock_tavily_client, # pylint: disable=redefined-outer-name - ): - """Test proper cleanup of resources""" - with patch( - "deep_research.agent_deep_research.main.StdIOStatefulClient", - return_value=mock_tavily_client, - ): - with patch.dict(os.environ, {"AGENT_OPERATION_DIR": "/tmp"}): - await main("Test query") - - mock_tavily_client.close.assert_called_once() - - def test_working_directory_creation( - self, - temp_working_dir, # pylint: disable=redefined-outer-name - ): - """Test working directory is created correctly""" - test_dir = os.path.join(temp_working_dir, "test_subdir") - os.makedirs(test_dir, exist_ok=True) - assert os.path.exists(test_dir) - os.makedirs(test_dir, exist_ok=True) # Should not raise error - - -class TestErrorHandling: - """Test suite for error handling scenarios""" - - @pytest.mark.asyncio - async def test_filesystem_errors( - self, - mock_tavily_client, # pylint: disable=redefined-outer-name - ): - """Test handling of filesystem errors""" - with patch( - "deep_research.agent_deep_research.main.StdIOStatefulClient", - return_value=mock_tavily_client, - ): - with patch.dict( - os.environ, - {"AGENT_OPERATION_DIR": "/invalid/path"}, - ): - with patch( - "os.makedirs", - side_effect=PermissionError("Permission denied"), - ): - with pytest.raises(PermissionError): - await main("Test query") - - -if __name__ == "__main__": - pytest.main(["-v", __file__]) diff --git a/tests/browser_agent_test.py b/tests/browser_agent_test.py deleted file mode 100644 index cfc3fc7..0000000 --- a/tests/browser_agent_test.py +++ /dev/null @@ -1,171 +0,0 @@ -# -*- coding: utf-8 -*- -from typing import Dict -from unittest.mock import AsyncMock, MagicMock, patch -import pytest -from agentscope.message import Msg -from agentscope.tool import Toolkit -from agentscope.memory import MemoryBase -from agentscope.model import ChatModelBase -from agentscope.formatter import FormatterBase -from browser_use.agent_browser.browser_agent import BrowserAgent - - -@pytest.fixture -def mock_dependencies() -> Dict[str, MagicMock]: - return { - "model": MagicMock(spec=ChatModelBase), - "formatter": MagicMock(spec=FormatterBase), - "memory": MagicMock(spec=MemoryBase), - "toolkit": MagicMock(spec=Toolkit), - } - - -@pytest.fixture -def agent( - # pylint: disable=redefined-outer-name - mock_dependencies: Dict[str, MagicMock], -) -> BrowserAgent: - return BrowserAgent( - name="TestBot", - model=mock_dependencies["model"], - formatter=mock_dependencies["formatter"], - memory=mock_dependencies["memory"], - toolkit=mock_dependencies["toolkit"], - start_url="https://test.com", - ) - - -# ----------------------------- -# ✅ Hook registration verification (adapted for ReActAgentBase) -# ----------------------------- -def test_hooks_registered( - agent: BrowserAgent, # pylint: disable=redefined-outer-name -) -> None: - """Verify instance-level hooks are registered""" - # Disable pylint warning for protected member access - assert hasattr( - agent, - "_instance_pre_reply_hooks", - ) # pylint: disable=protected-access - assert ( - "browser_agent_default_url_pre_reply" - # pylint: disable=protected-access - in agent._instance_pre_reply_hooks - ) - - assert hasattr( - agent, - "_instance_pre_reasoning_hooks", - ) # pylint: disable=protected-access - assert ( - "browser_agent_observe_pre_reasoning" - # pylint: disable=protected-access - in agent._instance_pre_reasoning_hooks - ) - - -# ----------------------------- -# ✅ Navigation hook test (direct hook invocation) -# ----------------------------- -@pytest.mark.asyncio -async def test_pre_reply_hook_navigation( - agent: BrowserAgent, # pylint: disable=redefined-outer-name -) -> None: - # pylint: disable=protected-access - agent._has_initial_navigated = False - - # Get instance-level hook function - # pylint: disable=protected-access - hook_func = agent._instance_pre_reply_hooks[ - "browser_agent_default_url_pre_reply" - ] - await hook_func(agent) # Directly invoke hook function - - # pylint: disable=protected-access - assert agent._has_initial_navigated is True - assert agent.toolkit.call_tool_function.called - - -# ----------------------------- -# ✅ Snapshot hook test (fix content attribute access issue) -# ----------------------------- -@pytest.mark.asyncio -async def test_observe_pre_reasoning( - agent: BrowserAgent, # pylint: disable=redefined-outer-name -) -> None: - # Mock tool response (fix: use Msg object with content attribute) - mock_response = AsyncMock() - mock_response.__aiter__.return_value = [ - Msg("system", [{"text": "Snapshot content"}], "system"), - ] - agent.toolkit.call_tool_function = AsyncMock( - return_value=mock_response, - ) - - # Replace memory add method - with patch.object( - agent.memory, - "add", - new_callable=AsyncMock, - ) as mock_add: - # Get instance-level hook function - # pylint: disable=protected-access - hook_func = agent._instance_pre_reasoning_hooks[ - "browser_agent_observe_pre_reasoning" - ] - await hook_func(agent) # Directly invoke hook function - - mock_add.assert_awaited_once() - added_msg = mock_add.call_args[0][0] - assert "Snapshot content" in added_msg.content[0]["text"] - - -# ----------------------------- -# ✅ Text filtering test (improved regex) -# ----------------------------- -def test_filter_execution_text( - agent: BrowserAgent, # pylint: disable=redefined-outer-name -) -> None: - text = """ - ### New console messages - Some console output - ### - ### Page state - YAML content here - ```yaml - key: value - ``` - Regular text content - """ - # pylint: disable=protected-access - filtered = agent._filter_execution_text(text) - - assert "console output" not in filtered - assert "key: value" not in filtered - assert "Regular text content" in filtered - assert "YAML content" in filtered - - -# ----------------------------- -# ✅ Memory summarization test (already passing) -# ----------------------------- -@pytest.mark.asyncio -async def test_memory_summarizing( - agent: BrowserAgent, # pylint: disable=redefined-outer-name -) -> None: - agent.memory.get_memory = AsyncMock( - return_value=[MagicMock(role="user", content="Original question")] - * 25, - ) - agent.memory.size = AsyncMock(return_value=25) - - agent.model = AsyncMock() - agent.model.return_value = MagicMock( - content=[MagicMock(text="Summary text")], - ) - - # pylint: disable=protected-access - await agent._memory_summarizing() - - assert agent.memory.clear.called - assert agent.memory.add.call_count == 2 # Original question + summary diff --git a/tests/browser_use_fullstack_runtime_test.py b/tests/browser_use_fullstack_runtime_test.py deleted file mode 100644 index b2a1152..0000000 --- a/tests/browser_use_fullstack_runtime_test.py +++ /dev/null @@ -1,145 +0,0 @@ -# -*- coding: utf-8 -*- -import asyncio -from types import SimpleNamespace -from unittest.mock import AsyncMock, MagicMock, patch -import pytest -import pytest_asyncio - -from quart.testing import QuartClient - -from browser_use.browser_use_fullstack_runtime.backend import ( - agentscope_browseruse_agent as agent_module, -) -from browser_use.browser_use_fullstack_runtime.backend import ( - async_quart_service as service, -) - -AgentscopeBrowseruseAgent = agent_module.AgentscopeBrowseruseAgent -RunStatus = agent_module.RunStatus -app = service.app - - -# ----------------------------- -# 🧪 Singleton Test Configuration -# ----------------------------- -@pytest.fixture(scope="session") -def event_loop(): - """Create an instance of the default event loop for session scope.""" - loop = asyncio.get_event_loop() - yield loop - loop.close() - - -@pytest_asyncio.fixture(scope="session") -async def agent_singleton(): - """Session-scoped single instance of AgentscopeBrowseruseAgent""" - with patch( - "browser_use.browser_use_fullstack_runtime." - "backend.agentscope_browseruse_agent.SandboxService", - ) as MockSandboxService, patch( - "browser_use.browser_use_fullstack_runtime." - "backend.agentscope_browseruse_agent.InMemoryMemoryService", - ) as MockMemoryService, patch( - "browser_use.browser_use_fullstack_runtime." - "backend.agentscope_browseruse_agent.InMemorySessionHistoryService", - ) as MockHistoryService, patch( - "agentscope_runtime.common.container_clients.docker_client.docker", - ) as mock_docker, patch( - "agentscope_runtime.sandbox.manager.sandbox_manager.SandboxManager", - ) as MockSandboxManager: - # ✅ Fully mock Docker dependencies - mock_api = MagicMock() - mock_api.version.return_value = {"ApiVersion": "1.0"} - - mock_client = MagicMock() - mock_client.api = mock_api - mock_client.from_env.return_value = mock_client - mock_client.__enter__.return_value = mock_client - - # ✅ Fully mock APIClient - mock_docker.APIClient = MagicMock() - mock_docker.from_env.return_value = mock_client - - # ✅ Fully mock SandboxManager - MockSandboxManager.return_value = MagicMock() - - # Configure InMemorySessionHistoryService - mock_session = MagicMock() - mock_session.create_session = AsyncMock() - MockHistoryService.return_value = mock_session - - # Configure InMemoryMemoryService - mock_memory = MagicMock() - mock_memory.start = AsyncMock() - MockMemoryService.return_value = mock_memory - - # Configure SandboxService - mock_sandbox = MagicMock() - mock_sandbox.start = AsyncMock() - MockSandboxService.return_value = mock_sandbox - - agent = AgentscopeBrowseruseAgent() - await agent.connect() - return agent - - -@pytest.fixture(scope="session") -async def test_app(): - """Create Quart application test client""" - async with QuartClient(app) as client: - yield client - - -# ----------------------------- -# ✅ AgentscopeBrowseruseAgent Singleton Tests -# ----------------------------- -@pytest.mark.asyncio -async def agent_singleton_singleton_initialization( - agent_singleton, # pylint: disable=redefined-outer-name -): - """Test agent singleton initialization""" - agent = agent_singleton # pylint: disable=redefined-outer-name - assert isinstance(agent, AgentscopeBrowseruseAgent) - assert hasattr(agent, "agent") - assert hasattr(agent, "runner") - - -@pytest.mark.asyncio -async def test_chat_method( - agent_singleton, -): # pylint: disable=redefined-outer-name - """Test chat method handles messages""" - mock_request = { - "messages": [ - {"role": "user", "content": "Hello"}, - ], - } - - # ✅ Create mock object with object/status properties - mock_event = SimpleNamespace( - object="message", - status=agent_module.RunStatus.Completed, - content=[{"type": "text", "text": "Test response"}], - ) - - with patch.object( - agent_singleton.runner, # pylint: disable=redefined-outer-name - "stream_query", - ) as mock_stream: - # ✅ Return object with properties - async def mock_stream_query(*_args, **_kwargs): - yield mock_event - - mock_stream.side_effect = mock_stream_query - - responses = [] - async for response in agent_singleton.chat( - # pylint: disable=redefined-outer-name - mock_request["messages"], - ): - responses.append(response) - - assert len(responses) == 1 - assert ( - responses[0][0]["text"] == "Test response" - ) # ✅ Fix property access diff --git a/tests/conversational_agents_chatbot_fullstack_runtime_webserver_test.py b/tests/conversational_agents_chatbot_fullstack_runtime_webserver_test.py deleted file mode 100644 index 1e6443d..0000000 --- a/tests/conversational_agents_chatbot_fullstack_runtime_webserver_test.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: utf-8 -*- -import os -import time -import tempfile -import pytest -import conversational_agents.chatbot_fullstack_runtime.backend.web_server as ws - - -app = ws.app -_db = ws.db -User = ws.User - - -def generate_unique_username(): - return f"testuser_{int(time.time())}" - - -@pytest.fixture -def client_and_username(): - """Create an Isolated Test Client and Username""" - db_fd, db_path = tempfile.mkstemp(suffix=".db") - app.config["SQLALCHEMY_DATABASE_URI"] = f"sqlite:///{db_path}" - app.config["TESTING"] = True - client = app.test_client() - - with app.app_context(): - _db.drop_all() - _db.create_all() - - # Generate Unique Username - username = generate_unique_username() - password = "testpass" - user = User(username=username, name="Test User") - user.set_password(password) - _db.session.add(user) - _db.session.commit() - - yield client, username, password - - os.close(db_fd) - os.unlink(db_path) - - -def test_user_login_success( - # pylint: disable=redefined-outer-name - client_and_username, -): - """Test Successful User Login""" - client, username, password = client_and_username - - response = client.post( - "/api/login", - json={ - "username": username, - "password": password, - }, - ) - assert response.status_code == 200 - data = response.get_json() - assert "id" in data - assert data["username"] == username diff --git a/tests/conversational_agents_chatbot_test.py b/tests/conversational_agents_chatbot_test.py deleted file mode 100644 index 0a7b76a..0000000 --- a/tests/conversational_agents_chatbot_test.py +++ /dev/null @@ -1,103 +0,0 @@ -# -*- coding: utf-8 -*- -from unittest.mock import AsyncMock -import pytest -from agentscope.message import Msg -from agentscope.agent import ReActAgent -from agentscope.tool import Toolkit - - -@pytest.mark.asyncio -class TestReActAgent: - """Test suite for the ReAct agent implementation""" - - @pytest.fixture - def test_agent(self): - """Fixture to create a test ReAct - agent with fully mocked dependencies""" - - async def model_response(): - yield Msg( - name="Friday", - content="Mocked model response", - role="assistant", - ) - - mock_model = AsyncMock() - mock_model.side_effect = model_response - - mock_formatter = AsyncMock() - mock_formatter.format = AsyncMock(return_value="Mocked prompt") - - mock_memory = AsyncMock() - mock_memory.get_memory = AsyncMock(return_value=[]) - - agent = ReActAgent( - name="Friday", - sys_prompt="You are a helpful assistant named Friday.", - model=mock_model, - formatter=mock_formatter, - toolkit=Toolkit(), - memory=mock_memory, - ) - - # pylint: disable=protected-access - agent._reasoning_hint_msgs = AsyncMock() - # pylint: disable=protected-access - agent._reasoning_hint_msgs.get_memory = AsyncMock(return_value=[]) - - return agent - - async def test_exit_command(self, test_agent, monkeypatch): - """Test exit command handling""" - - async def exit_model_response(*_args, **_kwargs): - yield Msg( - name="Friday", - content="exit", - role="assistant", - ) - - test_agent.model.side_effect = exit_model_response - - monkeypatch.setattr("builtins.input", lambda _: "exit") - - msg = Msg(name="User", content="exit", role="user") - response = await test_agent(msg) - - assert response.content == "exit" - - async def test_conversation_flow(self, monkeypatch): - """Test full conversation flow""" - - async def model_response(*_args, **_kwargs): - yield Msg( - name="Friday", - content="Thought: I need to use a tool\n" - "Action: execute_shell_command\n" - "Action Input: echo 'Hello World'", - role="assistant", - ) - - mock_model = AsyncMock() - mock_model.side_effect = model_response - - mock_formatter = AsyncMock() - mock_formatter.format = AsyncMock(return_value="Mocked prompt") - - mock_memory = AsyncMock() - mock_memory.get_memory = AsyncMock(return_value=[]) - - agent = ReActAgent( - name="Friday", - sys_prompt="You are a helpful assistant named Friday.", - model=mock_model, - formatter=mock_formatter, - toolkit=Toolkit(), - memory=mock_memory, - ) - - monkeypatch.setattr("builtins.input", lambda _: "Test command") - - msg = Msg(name="User", content="Test command", role="user") - response = await agent(msg) - assert "Thought:" in response.content diff --git a/tests/data_juicer_agent_test.py b/tests/data_juicer_agent_test.py deleted file mode 100644 index 506ca39..0000000 --- a/tests/data_juicer_agent_test.py +++ /dev/null @@ -1,248 +0,0 @@ -# -*- coding: utf-8 -*- -import os -from unittest.mock import AsyncMock, Mock, patch - -import pytest -from agentscope.agent import ReActAgent -from agentscope.model import DashScopeChatModel -from agentscope.tool import Toolkit -from agentscope.message import Msg -from agentscope.formatter import DashScopeChatFormatter -from agentscope.memory import InMemoryMemory -from agentscope.tool import ( - view_text_file, - write_text_file, -) - -# Import the main function and related components -from data_juicer_agent.main import main -from data_juicer_agent.agent_factory import create_agent -from data_juicer_agent.tools import ( - dj_toolkit, - dj_dev_toolkit, - dj_tools, - dj_dev_tools, - mcp_tools, - get_mcp_toolkit, - execute_safe_command, - query_dj_operators, - get_basic_files, - get_operator_example, - configure_data_juicer_path, -) - - -@pytest.fixture -def mock_toolkit(): - """Create a mocked Toolkit instance""" - return Mock(spec=Toolkit) - - -@pytest.fixture -def mock_model(): - """Create a mocked DashScopeChatModel""" - model = Mock(spec=DashScopeChatModel) - model.call = AsyncMock( - return_value=Msg("assistant", "test response", role="assistant"), - ) - return model - - -@pytest.fixture -def mock_formatter(): - """Create a mocked DashScopeChatFormatter""" - return Mock(spec=DashScopeChatFormatter) - - -@pytest.fixture -def mock_memory(): - """Create a mocked InMemoryMemory""" - return Mock(spec=InMemoryMemory) - - -@pytest.fixture -def mock_mcp_client(): - """Create a mocked MCP client""" - mock_client = Mock() - mock_client.name = "DJ_recipe_flow" - mock_client.connect = AsyncMock() - mock_client.close = AsyncMock() - mock_client.get_callable_function = AsyncMock() - mock_client.list_tools = AsyncMock() - return mock_client - - -@pytest.fixture -def mock_agent( - mock_model, # pylint: disable=redefined-outer-name - mock_formatter, # pylint: disable=redefined-outer-name - mock_toolkit, # pylint: disable=redefined-outer-name - mock_memory, # pylint: disable=redefined-outer-name -): - """Create a mocked ReActAgent instance""" - agent = Mock(spec=ReActAgent) - agent.model = mock_model - agent.formatter = mock_formatter - agent.toolkit = mock_toolkit - agent.memory = mock_memory - agent.__call__ = AsyncMock( - return_value=Msg("assistant", "test response", role="assistant"), - ) - return agent - - -class TestDataJuicerAgent: - """Test suite for the data_juicer_agent functionality""" - - def named_mock_agent( - self, - name, - mock_agent, # pylint: disable=redefined-outer-name - ): - """Create a named mock agent for testing""" - agent_instance = Mock(spec=ReActAgent) - agent_instance.model = mock_agent.model - agent_instance.formatter = mock_agent.formatter - agent_instance.toolkit = mock_agent.toolkit - agent_instance.memory = mock_agent.memory - agent_instance.__call__ = mock_agent.__call__ - agent_instance.name = name - return agent_instance - - def _named_mock_agent_side_effect( - self, - mock_agent, # pylint: disable=redefined-outer-name - ): - """Side effect function for creating named mock agents""" - return lambda name, *args, **kwargs: self.named_mock_agent( - name, - mock_agent, - *args, - **kwargs, - ) - - async def mock_user_func(self): - return Msg("user", "exit", role="user") - - def test_dj_toolkit_initialization(self): - """Test DJ toolkit initialization and tool registration""" - assert dj_toolkit.tools.get("execute_safe_command") is not None - assert dj_toolkit.tools.get("view_text_file") is not None - assert dj_toolkit.tools.get("write_text_file") is not None - assert dj_toolkit.tools.get("query_dj_operators") is not None - - # Verify tool list contains expected tools - expected_tools = [ - execute_safe_command, - view_text_file, - write_text_file, - query_dj_operators, - ] - assert len(dj_tools) == len(expected_tools) - for tool in expected_tools: - assert tool in dj_tools - - def test_dj_dev_toolkit_initialization(self): - """Test DJ development toolkit initialization and tool registration""" - assert dj_dev_toolkit.tools.get("view_text_file") is not None - assert dj_dev_toolkit.tools.get("write_text_file") is not None - assert dj_dev_toolkit.tools.get("get_basic_files") is not None - assert dj_dev_toolkit.tools.get("get_operator_example") is not None - assert ( - dj_dev_toolkit.tools.get("configure_data_juicer_path") is not None - ) - - # Verify tool list contains expected tools - expected_tools = [ - view_text_file, - write_text_file, - get_basic_files, - get_operator_example, - configure_data_juicer_path, - ] - assert len(dj_dev_tools) == len(expected_tools) - for tool in expected_tools: - assert tool in dj_dev_tools - - @pytest.mark.asyncio - async def test_mcp_tools_list( - self, - mock_mcp_client, # pylint: disable=redefined-outer-name - ): - """Test MCP tools list contains expected tools""" - with patch( - "agentscope.mcp.HttpStatefulClient", - return_value=mock_mcp_client, - ) as mock_client_cls: - await get_mcp_toolkit() - assert mock_client_cls.assert_called_once - - expected_tools = [view_text_file, write_text_file] - assert len(mcp_tools) == len(expected_tools) - for tool in expected_tools: - assert tool in mcp_tools - - @pytest.mark.asyncio - async def test_agent_initialization( - self, - mock_model, # pylint: disable=redefined-outer-name - mock_formatter, # pylint: disable=redefined-outer-name - mock_toolkit, # pylint: disable=redefined-outer-name - mock_memory, # pylint: disable=redefined-outer-name - ): - """Test ReActAgent initialization""" - with patch.dict(os.environ, {"DASHSCOPE_API_KEY": "test_key"}): - agent = create_agent( - name="DataJuicer", - sys_prompt="You are {name}, a agent.", - toolkit=mock_toolkit, - description="test description", - model=mock_model, - formatter=mock_formatter, - memory=mock_memory, - ) - - assert agent.name == "DataJuicer" - assert "DataJuicer" in agent.sys_prompt - assert "test" in agent.__doc__ - assert agent.model == mock_model - assert agent.formatter == mock_formatter - assert agent.toolkit == mock_toolkit - assert agent.memory == mock_memory - assert isinstance(agent, ReActAgent) - - @pytest.mark.asyncio - async def test_main_with_multiple_agents_loading( - self, - mock_agent, # pylint: disable=redefined-outer-name - mock_mcp_client, # pylint: disable=redefined-outer-name - ): - """Test main function loads multiple agents successfully""" - with patch.dict(os.environ, {"DASHSCOPE_API_KEY": "test_key"}): - mock_mcp_clients = [mock_mcp_client] - - with patch( - "data_juicer_agent.tools.mcp_helpers._create_clients", - return_value=mock_mcp_clients, - ): - with patch( - "data_juicer_agent.main.create_agent", - side_effect=self._named_mock_agent_side_effect(mock_agent), - ) as mock_create_agent: - with patch( - "data_juicer_agent.main.user", - side_effect=self.mock_user_func, - ): - await main( - use_studio=False, - available_agents=["dj", "dj_dev", "dj_mcp"], - retrieval_mode="auto", - ) - - # Validate multiple agents are correctly created - # (dj, dj_dev, dj_mcp, and router) - assert mock_create_agent.call_count == 4 - - -if __name__ == "__main__": - pytest.main(["-v", __file__]) diff --git a/tests/evaluation_test.py b/tests/evaluation_test.py deleted file mode 100644 index 2b728fc..0000000 --- a/tests/evaluation_test.py +++ /dev/null @@ -1,163 +0,0 @@ -# -*- coding: utf-8 -*- -import os -from unittest.mock import Mock, AsyncMock, patch -from typing import List, Dict, Any, Tuple, Callable - -import pytest -from agentscope.evaluate import Task, ACEPhone, ACEBenchmark - -# Import the main module from the correct path -from evaluation.ace_bench import main as ace_main - - -class TestReActAgentSolution: - """Test suite for the ReAct agent solution function""" - - @pytest.fixture - def mock_task(self) -> Task: - """Create a mock ACEBench task""" - task = Mock(spec=Task) - task.input = "Test input query" - task.metadata = { - "tools": self._create_mock_tools(), - "phone": Mock(spec=ACEPhone), - } - return task - - @pytest.fixture - def mock_pre_hook(self) -> Mock: - """Create a mock pre-hook function that returns None""" - - def pre_hook_return(): - """Mock function that returns None (no modifications)""" - return None - - mock = Mock() - mock.__name__ = "save_logging" - mock.side_effect = ( - pre_hook_return # ✅ Return None to avoid parameter pollution - ) - return mock - - def _create_mock_tools(self) -> List[Tuple[Callable, Dict[str, Any]]]: - """Create mock tool functions with schemas""" - - def mock_tool(): - return "tool_response" - - tool_schema = { - "type": "function", - "function": { - "name": "mock_tool", - "description": "A mock tool for testing", - "parameters": { - "type": "object", - "properties": { - "param1": {"type": "string"}, - "param2": {"type": "number"}, - }, - "required": ["param1"], - }, - }, - } - - return [(mock_tool, tool_schema)] - - @pytest.mark.asyncio - async def test_error_handling( - self, - mock_task: Task, - mock_pre_hook: Mock, - ) -> None: - """Test error handling in the solution function""" - with patch.dict(os.environ, {"DASHSCOPE_API_KEY": "test_key"}): - # Mock a failure case - with patch( - "evaluation.ace_bench.main.Toolkit.register_tool_function", - side_effect=Exception("Registration error"), - ): - with pytest.raises(Exception) as exc_info: - await ace_main.react_agent_solution( - mock_task, - mock_pre_hook, - ) - - assert "Registration error" in str(exc_info.value) - - -class TestMainFunction: - """Test suite for the main function""" - - @pytest.fixture - def mock_args(self, tmpdir) -> Mock: - """Create mock command-line arguments with temporary directories""" - args = Mock() - args.data_dir = str(tmpdir / "data") - args.result_dir = str(tmpdir / "results") - args.n_workers = 2 - return args - - @pytest.mark.asyncio - async def test_evaluator_initialization(self, mock_args: Mock) -> None: - """Test evaluator initialization""" - with patch( - "evaluation.ace_bench.main.ArgumentParser.parse_args", - return_value=mock_args, - ): - with patch( - "evaluation.ace_bench.main.RayEvaluator", - ) as mock_evaluator_class: - mock_evaluator = AsyncMock() - mock_evaluator_class.return_value = mock_evaluator - - # ✅ Simulate _download_data and _load_data - with patch( - "agentscope.evaluate._ace_benchmark." - "_ace_benchmark.ACEBenchmark._download_data", - ): - with patch( - "agentscope.evaluate._ace_benchmark." - "_ace_benchmark.ACEBenchmark._load_data", - return_value=[], - ): - # Run main function - await ace_main.main() - - # Verify evaluator initialization - mock_evaluator_class.assert_called_once() - call_args = mock_evaluator_class.call_args[1] - assert call_args["n_workers"] == 2 - assert isinstance(call_args["benchmark"], ACEBenchmark) - assert call_args["benchmark"].data_dir == mock_args.data_dir - - @pytest.mark.asyncio - async def test_evaluation_execution(self, mock_args: Mock) -> None: - """Test evaluation execution""" - with patch( - "evaluation.ace_bench.main.ArgumentParser.parse_args", - return_value=mock_args, - ): - with patch( - "evaluation.ace_bench.main.RayEvaluator", - ) as mock_evaluator_class: - mock_evaluator = AsyncMock() - mock_evaluator.run = AsyncMock() - mock_evaluator_class.return_value = mock_evaluator - - # ✅ Simulate _download_data and _load_data - with patch( - "agentscope.evaluate._ace_benchmark._ace_benchmark." - "ACEBenchmark._download_data", - ): - with patch( - "agentscope.evaluate._ace_benchmark." - "_ace_benchmark.ACEBenchmark._load_data", - return_value=[], - ): - # Run main function - await ace_main.main() - - # Verify evaluation execution - mock_evaluator.run.assert_called_once_with( - ace_main.react_agent_solution, - ) diff --git a/tests/game_test.py b/tests/game_test.py deleted file mode 100644 index 8707a6d..0000000 --- a/tests/game_test.py +++ /dev/null @@ -1,116 +0,0 @@ -# -*- coding: utf-8 -*- -from unittest.mock import AsyncMock, patch, MagicMock -import pytest -from agentscope.agent import ReActAgent -from agentscope.model import ChatModelBase -from agentscope.formatter import FormatterBase - -# Import modules to test -from games.game_werewolves import game, utils, structured_model - - -class HunterModelMock: - def __init__(self, **kwargs): - self._data = { - "name": kwargs.get("name", None), - "shoot": kwargs.get("shoot", False), - } - self.metadata = {"shoot": self._data["name"] is not None} - - def model_dump(self): - return self._data - - @property - def name(self): - return self._data["name"] - - -@pytest.mark.asyncio -async def test_werewolves_discussion() -> None: - mock_hub = AsyncMock() - mock_hub.__aenter__.return_value = mock_hub - mock_hub.__aexit__.return_value = AsyncMock() - - with patch("games.game_werewolves.game.MsgHub", return_value=mock_hub): - mock_agent = AsyncMock() - mock_agent.name = "Player1" - - agents = [mock_agent for _ in range(9)] - await game.werewolves_game(agents) - assert True - - -@pytest.mark.asyncio -async def test_witch_resurrect() -> None: - async def mock_model(**kwargs): - return {"resurrect": kwargs.get("resurrect", False)} - - with patch( - "games.game_werewolves.game.WitchResurrectModel", - side_effect=mock_model, - ): - result = await game.WitchResurrectModel(**{"resurrect": True}) - assert result["resurrect"] is True - - -# ----------------------------- -# Test: utils.py -# ----------------------------- -def test_majority_vote() -> None: - votes = ["Player1", "Player1", "Player2"] - result, _ = utils.majority_vote(votes) - assert result == "Player1" - - -def test_names_to_str_single() -> None: - assert utils.names_to_str(["Player1"]) == "Player1" - - -def test_players_role_mapping() -> None: - players = utils.Players() - mock_agent = utils.EchoAgent() - mock_agent.name = "Player1" - - players.add_player(mock_agent, "werewolf") - assert players.name_to_role["Player1"] == "werewolf" - assert len(players.werewolves) == 1 - - -def test_vote_model_generation() -> None: - mock_model = MagicMock(spec=ChatModelBase) - mock_formatter = MagicMock(spec=FormatterBase) - - agents = [ - ReActAgent( - name=f"Player{i}", - sys_prompt=f"Vote system prompt {i}", - model=mock_model, - formatter=mock_formatter, - ) - for i in range(3) - ] - - VoteModel = structured_model.get_vote_model(agents) - assert "vote" in VoteModel.model_fields - assert ( - VoteModel.model_fields["vote"].description - == "The name of the player you want to vote for" - ) - - -def test_witch_poison_model_fields() -> None: - mock_model = MagicMock(spec=ChatModelBase) - mock_formatter = MagicMock(spec=FormatterBase) - - agents = [ - ReActAgent( - name="Player1", - sys_prompt="Poison system prompt", - model=mock_model, - formatter=mock_formatter, - ), - ] - - PoisonModel = structured_model.get_poison_model(agents) - assert "poison" in PoisonModel.model_fields - assert "name" in PoisonModel.model_fields