Apply automatic linting fixes to tests directory

Co-Authored-By: Joe Moura <joao@crewai.com>
This commit is contained in:
Devin AI
2025-05-12 13:31:07 +00:00
parent ad1ea46bbb
commit 46621113af
62 changed files with 1738 additions and 1821 deletions

View File

@@ -24,7 +24,7 @@ def vcr_config(request) -> dict:
@pytest.mark.vcr(filter_headers=["authorization"])
def test_delegate_work():
def test_delegate_work() -> None:
result = delegate_tool.run(
coworker="researcher",
task="share your take on AI Agents",
@@ -38,7 +38,7 @@ def test_delegate_work():
@pytest.mark.vcr(filter_headers=["authorization"])
def test_delegate_work_with_wrong_co_worker_variable():
def test_delegate_work_with_wrong_co_worker_variable() -> None:
result = delegate_tool.run(
coworker="researcher",
task="share your take on AI Agents",
@@ -52,7 +52,7 @@ def test_delegate_work_with_wrong_co_worker_variable():
@pytest.mark.vcr(filter_headers=["authorization"])
def test_ask_question():
def test_ask_question() -> None:
result = ask_tool.run(
coworker="researcher",
question="do you hate AI Agents?",
@@ -66,7 +66,7 @@ def test_ask_question():
@pytest.mark.vcr(filter_headers=["authorization"])
def test_ask_question_with_wrong_co_worker_variable():
def test_ask_question_with_wrong_co_worker_variable() -> None:
result = ask_tool.run(
coworker="researcher",
question="do you hate AI Agents?",
@@ -80,7 +80,7 @@ def test_ask_question_with_wrong_co_worker_variable():
@pytest.mark.vcr(filter_headers=["authorization"])
def test_delegate_work_withwith_coworker_as_array():
def test_delegate_work_withwith_coworker_as_array() -> None:
result = delegate_tool.run(
coworker="[researcher]",
task="share your take on AI Agents",
@@ -94,7 +94,7 @@ def test_delegate_work_withwith_coworker_as_array():
@pytest.mark.vcr(filter_headers=["authorization"])
def test_ask_question_with_coworker_as_array():
def test_ask_question_with_coworker_as_array() -> None:
result = ask_tool.run(
coworker="[researcher]",
question="do you hate AI Agents?",
@@ -107,7 +107,7 @@ def test_ask_question_with_coworker_as_array():
)
def test_delegate_work_to_wrong_agent():
def test_delegate_work_to_wrong_agent() -> None:
result = ask_tool.run(
coworker="writer",
question="share your take on AI Agents",
@@ -120,7 +120,7 @@ def test_delegate_work_to_wrong_agent():
)
def test_ask_question_to_wrong_agent():
def test_ask_question_to_wrong_agent() -> None:
result = ask_tool.run(
coworker="writer",
question="do you hate AI Agents?",

View File

@@ -1,13 +1,11 @@
import asyncio
import inspect
import unittest
from typing import Any, Callable, Dict, List
from collections.abc import Callable
from unittest.mock import patch
from crewai.tools import BaseTool, tool
def test_creating_a_tool_using_annotation():
def test_creating_a_tool_using_annotation() -> None:
@tool("Name of my tool")
def my_tool(question: str) -> str:
"""Clear description for what this tool is useful for, your agent will need this information to use it."""
@@ -20,7 +18,7 @@ def test_creating_a_tool_using_annotation():
== "Tool Name: Name of my tool\nTool Arguments: {'question': {'description': None, 'type': 'str'}}\nTool Description: Clear description for what this tool is useful for, your agent will need this information to use it."
)
assert my_tool.args_schema.model_json_schema()["properties"] == {
"question": {"title": "Question", "type": "string"}
"question": {"title": "Question", "type": "string"},
}
assert (
my_tool.func("What is the meaning of life?") == "What is the meaning of life?"
@@ -34,7 +32,7 @@ def test_creating_a_tool_using_annotation():
== "Tool Name: Name of my tool\nTool Arguments: {'question': {'description': None, 'type': 'str'}}\nTool Description: Clear description for what this tool is useful for, your agent will need this information to use it."
)
assert converted_tool.args_schema.model_json_schema()["properties"] == {
"question": {"title": "Question", "type": "string"}
"question": {"title": "Question", "type": "string"},
}
assert (
converted_tool.func("What is the meaning of life?")
@@ -42,7 +40,7 @@ def test_creating_a_tool_using_annotation():
)
def test_creating_a_tool_using_baseclass():
def test_creating_a_tool_using_baseclass() -> None:
class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = "Clear description for what this tool is useful for, your agent will need this information to use it."
@@ -59,7 +57,7 @@ def test_creating_a_tool_using_baseclass():
== "Tool Name: Name of my tool\nTool Arguments: {'question': {'description': None, 'type': 'str'}}\nTool Description: Clear description for what this tool is useful for, your agent will need this information to use it."
)
assert my_tool.args_schema.model_json_schema()["properties"] == {
"question": {"title": "Question", "type": "string"}
"question": {"title": "Question", "type": "string"},
}
assert my_tool.run("What is the meaning of life?") == "What is the meaning of life?"
@@ -71,7 +69,7 @@ def test_creating_a_tool_using_baseclass():
== "Tool Name: Name of my tool\nTool Arguments: {'question': {'description': None, 'type': 'str'}}\nTool Description: Clear description for what this tool is useful for, your agent will need this information to use it."
)
assert converted_tool.args_schema.model_json_schema()["properties"] == {
"question": {"title": "Question", "type": "string"}
"question": {"title": "Question", "type": "string"},
}
assert (
converted_tool._run("What is the meaning of life?")
@@ -79,7 +77,7 @@ def test_creating_a_tool_using_baseclass():
)
def test_setting_cache_function():
def test_setting_cache_function() -> None:
class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = "Clear description for what this tool is useful for, your agent will need this information to use it."
@@ -93,7 +91,7 @@ def test_setting_cache_function():
assert not my_tool.cache_function()
def test_default_cache_function_is_true():
def test_default_cache_function_is_true() -> None:
class MyCustomTool(BaseTool):
name: str = "Name of my tool"
description: str = "Clear description for what this tool is useful for, your agent will need this information to use it."
@@ -106,30 +104,31 @@ def test_default_cache_function_is_true():
assert my_tool.cache_function()
def test_result_as_answer_in_tool_decorator():
def test_result_as_answer_in_tool_decorator() -> None:
@tool("Tool with result as answer", result_as_answer=True)
def my_tool_with_result_as_answer(question: str) -> str:
"""This tool will return its result as the final answer."""
return question
assert my_tool_with_result_as_answer.result_as_answer is True
converted_tool = my_tool_with_result_as_answer.to_structured_tool()
assert converted_tool.result_as_answer is True
@tool("Tool with default result_as_answer")
def my_tool_with_default(question: str) -> str:
"""This tool uses the default result_as_answer value."""
return question
assert my_tool_with_default.result_as_answer is False
converted_tool = my_tool_with_default.to_structured_tool()
assert converted_tool.result_as_answer is False
class SyncTool(BaseTool):
"""Test implementation with a synchronous _run method"""
"""Test implementation with a synchronous _run method."""
name: str = "sync_tool"
description: str = "A synchronous tool for testing"
@@ -139,7 +138,8 @@ class SyncTool(BaseTool):
class AsyncTool(BaseTool):
"""Test implementation with an asynchronous _run method"""
"""Test implementation with an asynchronous _run method."""
name: str = "async_tool"
description: str = "An asynchronous tool for testing"
@@ -149,7 +149,7 @@ class AsyncTool(BaseTool):
return f"Processed {input_text} asynchronously"
def test_sync_run_returns_direct_result():
def test_sync_run_returns_direct_result() -> None:
"""Test that _run in a synchronous tool returns a direct result, not a coroutine."""
tool = SyncTool()
result = tool._run(input_text="hello")
@@ -161,7 +161,7 @@ def test_sync_run_returns_direct_result():
assert run_result == "Processed hello synchronously"
def test_async_run_returns_coroutine():
def test_async_run_returns_coroutine() -> None:
"""Test that _run in an asynchronous tool returns a coroutine object."""
tool = AsyncTool()
result = tool._run(input_text="hello")
@@ -170,11 +170,11 @@ def test_async_run_returns_coroutine():
result.close() # Clean up the coroutine
def test_run_calls_asyncio_run_for_async_tools():
def test_run_calls_asyncio_run_for_async_tools() -> None:
"""Test that asyncio.run is called when using async tools."""
async_tool = AsyncTool()
with patch('asyncio.run') as mock_run:
with patch("asyncio.run") as mock_run:
mock_run.return_value = "Processed test asynchronously"
async_result = async_tool.run(input_text="test")
@@ -182,11 +182,11 @@ def test_run_calls_asyncio_run_for_async_tools():
assert async_result == "Processed test asynchronously"
def test_run_does_not_call_asyncio_run_for_sync_tools():
def test_run_does_not_call_asyncio_run_for_sync_tools() -> None:
"""Test that asyncio.run is NOT called when using sync tools."""
sync_tool = SyncTool()
with patch('asyncio.run') as mock_run:
with patch("asyncio.run") as mock_run:
sync_result = sync_tool.run(input_text="test")
mock_run.assert_not_called()

View File

@@ -1,4 +1,3 @@
from typing import Optional
import pytest
from pydantic import BaseModel, Field
@@ -26,8 +25,8 @@ def schema_class():
class InternalCrewStructuredTool:
def test_initialization(self, basic_function, schema_class):
"""Test basic initialization of CrewStructuredTool"""
def test_initialization(self, basic_function, schema_class) -> None:
"""Test basic initialization of CrewStructuredTool."""
tool = CrewStructuredTool(
name="test_tool",
description="Test tool description",
@@ -40,10 +39,10 @@ class InternalCrewStructuredTool:
assert tool.func == basic_function
assert tool.args_schema == schema_class
def test_from_function(self, basic_function):
"""Test creating tool from function"""
def test_from_function(self, basic_function) -> None:
"""Test creating tool from function."""
tool = CrewStructuredTool.from_function(
func=basic_function, name="test_tool", description="Test description"
func=basic_function, name="test_tool", description="Test description",
)
assert tool.name == "test_tool"
@@ -51,8 +50,8 @@ class InternalCrewStructuredTool:
assert tool.func == basic_function
assert isinstance(tool.args_schema, type(BaseModel))
def test_validate_function_signature(self, basic_function, schema_class):
"""Test function signature validation"""
def test_validate_function_signature(self, basic_function, schema_class) -> None:
"""Test function signature validation."""
tool = CrewStructuredTool(
name="test_tool",
description="Test tool",
@@ -64,44 +63,44 @@ class InternalCrewStructuredTool:
tool._validate_function_signature()
@pytest.mark.asyncio
async def test_ainvoke(self, basic_function):
"""Test asynchronous invocation"""
async def test_ainvoke(self, basic_function) -> None:
"""Test asynchronous invocation."""
tool = CrewStructuredTool.from_function(func=basic_function, name="test_tool")
result = await tool.ainvoke(input={"param1": "test"})
assert result == "test 0"
def test_parse_args_dict(self, basic_function):
"""Test parsing dictionary arguments"""
def test_parse_args_dict(self, basic_function) -> None:
"""Test parsing dictionary arguments."""
tool = CrewStructuredTool.from_function(func=basic_function, name="test_tool")
parsed = tool._parse_args({"param1": "test", "param2": 42})
assert parsed["param1"] == "test"
assert parsed["param2"] == 42
def test_parse_args_string(self, basic_function):
"""Test parsing string arguments"""
def test_parse_args_string(self, basic_function) -> None:
"""Test parsing string arguments."""
tool = CrewStructuredTool.from_function(func=basic_function, name="test_tool")
parsed = tool._parse_args('{"param1": "test", "param2": 42}')
assert parsed["param1"] == "test"
assert parsed["param2"] == 42
def test_complex_types(self):
"""Test handling of complex parameter types"""
def test_complex_types(self) -> None:
"""Test handling of complex parameter types."""
def complex_func(nested: dict, items: list) -> str:
"""Process complex types."""
return f"Processed {len(items)} items with {len(nested)} nested keys"
tool = CrewStructuredTool.from_function(
func=complex_func, name="test_tool", description="Test complex types"
func=complex_func, name="test_tool", description="Test complex types",
)
result = tool.invoke({"nested": {"key": "value"}, "items": [1, 2, 3]})
assert result == "Processed 3 items with 1 nested keys"
def test_schema_inheritance(self):
"""Test tool creation with inherited schema"""
def test_schema_inheritance(self) -> None:
"""Test tool creation with inherited schema."""
def extended_func(base_param: str, extra_param: int) -> str:
"""Test function with inherited schema."""
@@ -114,25 +113,25 @@ class InternalCrewStructuredTool:
extra_param: int
tool = CrewStructuredTool.from_function(
func=extended_func, name="test_tool", args_schema=ExtendedSchema
func=extended_func, name="test_tool", args_schema=ExtendedSchema,
)
result = tool.invoke({"base_param": "test", "extra_param": 42})
assert result == "test 42"
def test_default_values_in_schema(self):
"""Test handling of default values in schema"""
def test_default_values_in_schema(self) -> None:
"""Test handling of default values in schema."""
def default_func(
required_param: str,
optional_param: str = "default",
nullable_param: Optional[int] = None,
nullable_param: int | None = None,
) -> str:
"""Test function with default values."""
return f"{required_param} {optional_param} {nullable_param}"
tool = CrewStructuredTool.from_function(
func=default_func, name="test_tool", description="Test defaults"
func=default_func, name="test_tool", description="Test defaults",
)
# Test with minimal parameters
@@ -141,6 +140,6 @@ class InternalCrewStructuredTool:
# Test with all parameters
result = tool.invoke(
{"required_param": "test", "optional_param": "custom", "nullable_param": 42}
{"required_param": "test", "optional_param": "custom", "nullable_param": 42},
)
assert result == "test custom 42"

View File

@@ -20,10 +20,10 @@ from crewai.utilities.events.tool_usage_events import (
class RandomNumberToolInput(BaseModel):
min_value: int = Field(
..., description="The minimum value of the range (inclusive)"
..., description="The minimum value of the range (inclusive)",
)
max_value: int = Field(
..., description="The maximum value of the range (inclusive)"
..., description="The maximum value of the range (inclusive)",
)
@@ -52,19 +52,19 @@ example_task = Task(
)
def test_random_number_tool_range():
def test_random_number_tool_range() -> None:
tool = RandomNumberTool()
result = tool._run(1, 10)
assert 1 <= result <= 10
def test_random_number_tool_invalid_range():
def test_random_number_tool_invalid_range() -> None:
tool = RandomNumberTool()
with pytest.raises(ValueError):
tool._run(10, 1) # min_value > max_value
def test_random_number_tool_schema():
def test_random_number_tool_schema() -> None:
tool = RandomNumberTool()
# Get the schema using model_json_schema()
@@ -93,7 +93,7 @@ def test_random_number_tool_schema():
)
def test_tool_usage_render():
def test_tool_usage_render() -> None:
tool = RandomNumberTool()
tool_usage = ToolUsage(
@@ -128,7 +128,7 @@ def test_tool_usage_render():
)
def test_validate_tool_input_booleans_and_none():
def test_validate_tool_input_booleans_and_none() -> None:
# Create a ToolUsage instance with mocks
tool_usage = ToolUsage(
tools_handler=MagicMock(),
@@ -147,7 +147,7 @@ def test_validate_tool_input_booleans_and_none():
assert arguments == expected_arguments
def test_validate_tool_input_mixed_types():
def test_validate_tool_input_mixed_types() -> None:
# Create a ToolUsage instance with mocks
tool_usage = ToolUsage(
tools_handler=MagicMock(),
@@ -166,7 +166,7 @@ def test_validate_tool_input_mixed_types():
assert arguments == expected_arguments
def test_validate_tool_input_single_quotes():
def test_validate_tool_input_single_quotes() -> None:
# Create a ToolUsage instance with mocks
tool_usage = ToolUsage(
tools_handler=MagicMock(),
@@ -185,7 +185,7 @@ def test_validate_tool_input_single_quotes():
assert arguments == expected_arguments
def test_validate_tool_input_invalid_json_repairable():
def test_validate_tool_input_invalid_json_repairable() -> None:
# Create a ToolUsage instance with mocks
tool_usage = ToolUsage(
tools_handler=MagicMock(),
@@ -204,7 +204,7 @@ def test_validate_tool_input_invalid_json_repairable():
assert arguments == expected_arguments
def test_validate_tool_input_with_special_characters():
def test_validate_tool_input_with_special_characters() -> None:
# Create a ToolUsage instance with mocks
tool_usage = ToolUsage(
tools_handler=MagicMock(),
@@ -223,7 +223,7 @@ def test_validate_tool_input_with_special_characters():
assert arguments == expected_arguments
def test_validate_tool_input_none_input():
def test_validate_tool_input_none_input() -> None:
tool_usage = ToolUsage(
tools_handler=MagicMock(),
tools=[],
@@ -237,7 +237,7 @@ def test_validate_tool_input_none_input():
assert arguments == {}
def test_validate_tool_input_valid_json():
def test_validate_tool_input_valid_json() -> None:
tool_usage = ToolUsage(
tools_handler=MagicMock(),
tools=[],
@@ -254,7 +254,7 @@ def test_validate_tool_input_valid_json():
assert arguments == expected_arguments
def test_validate_tool_input_python_dict():
def test_validate_tool_input_python_dict() -> None:
tool_usage = ToolUsage(
tools_handler=MagicMock(),
tools=[],
@@ -271,7 +271,7 @@ def test_validate_tool_input_python_dict():
assert arguments == expected_arguments
def test_validate_tool_input_json5_unquoted_keys():
def test_validate_tool_input_json5_unquoted_keys() -> None:
tool_usage = ToolUsage(
tools_handler=MagicMock(),
tools=[],
@@ -288,7 +288,7 @@ def test_validate_tool_input_json5_unquoted_keys():
assert arguments == expected_arguments
def test_validate_tool_input_with_trailing_commas():
def test_validate_tool_input_with_trailing_commas() -> None:
tool_usage = ToolUsage(
tools_handler=MagicMock(),
tools=[],
@@ -305,7 +305,7 @@ def test_validate_tool_input_with_trailing_commas():
assert arguments == expected_arguments
def test_validate_tool_input_invalid_input():
def test_validate_tool_input_invalid_input() -> None:
# Create mock agent with proper string values
mock_agent = MagicMock()
mock_agent.key = "test_agent_key" # Must be a string
@@ -348,7 +348,7 @@ def test_validate_tool_input_invalid_input():
assert arguments == {}
def test_validate_tool_input_complex_structure():
def test_validate_tool_input_complex_structure() -> None:
tool_usage = ToolUsage(
tools_handler=MagicMock(),
tools=[],
@@ -384,7 +384,7 @@ def test_validate_tool_input_complex_structure():
assert arguments == expected_arguments
def test_validate_tool_input_code_content():
def test_validate_tool_input_code_content() -> None:
tool_usage = ToolUsage(
tools_handler=MagicMock(),
tools=[],
@@ -404,7 +404,7 @@ def test_validate_tool_input_code_content():
assert arguments == expected_arguments
def test_validate_tool_input_with_escaped_quotes():
def test_validate_tool_input_with_escaped_quotes() -> None:
tool_usage = ToolUsage(
tools_handler=MagicMock(),
tools=[],
@@ -421,7 +421,7 @@ def test_validate_tool_input_with_escaped_quotes():
assert arguments == expected_arguments
def test_validate_tool_input_large_json_content():
def test_validate_tool_input_large_json_content() -> None:
tool_usage = ToolUsage(
tools_handler=MagicMock(),
tools=[],
@@ -441,7 +441,7 @@ def test_validate_tool_input_large_json_content():
assert arguments == expected_arguments
def test_tool_selection_error_event_direct():
def test_tool_selection_error_event_direct() -> None:
"""Test tool selection error event emission directly from ToolUsage class."""
mock_agent = MagicMock()
mock_agent.key = "test_key"
@@ -473,10 +473,10 @@ def test_tool_selection_error_event_direct():
received_events = []
@crewai_event_bus.on(ToolSelectionErrorEvent)
def event_handler(source, event):
def event_handler(source, event) -> None:
received_events.append(event)
with pytest.raises(Exception) as exc_info:
with pytest.raises(Exception):
tool_usage._select_tool("Non Existent Tool")
assert len(received_events) == 1
event = received_events[0]
@@ -490,7 +490,7 @@ def test_tool_selection_error_event_direct():
assert "don't exist" in event.error
received_events.clear()
with pytest.raises(Exception) as exc_info:
with pytest.raises(Exception):
tool_usage._select_tool("")
assert len(received_events) == 1
@@ -504,7 +504,7 @@ def test_tool_selection_error_event_direct():
assert "forgot the Action name" in event.error
def test_tool_validate_input_error_event():
def test_tool_validate_input_error_event() -> None:
"""Test tool validation input error event emission from ToolUsage class."""
# Mock agent and required components
mock_agent = MagicMock()
@@ -558,12 +558,12 @@ def test_tool_validate_input_error_event():
received_events = []
@crewai_event_bus.on(ToolValidateInputErrorEvent)
def event_handler(source, event):
def event_handler(source, event) -> None:
received_events.append(event)
# Test invalid input
invalid_input = "invalid json {[}"
with pytest.raises(Exception) as exc_info:
with pytest.raises(Exception):
tool_usage._validate_tool_input(invalid_input)
# Verify event was emitted
@@ -576,7 +576,7 @@ def test_tool_validate_input_error_event():
assert "must be a valid dictionary" in event.error
def test_tool_usage_finished_event_with_result():
def test_tool_usage_finished_event_with_result() -> None:
"""Test that ToolUsageFinishedEvent is emitted with correct result attributes."""
# Create mock agent with proper string values
mock_agent = MagicMock()
@@ -618,7 +618,7 @@ def test_tool_usage_finished_event_with_result():
received_events = []
@crewai_event_bus.on(ToolUsageFinishedEvent)
def event_handler(source, event):
def event_handler(source, event) -> None:
received_events.append(event)
# Call on_tool_use_finished with test data
@@ -652,7 +652,7 @@ def test_tool_usage_finished_event_with_result():
assert event.type == "tool_usage_finished"
def test_tool_usage_finished_event_with_cached_result():
def test_tool_usage_finished_event_with_cached_result() -> None:
"""Test that ToolUsageFinishedEvent is emitted with correct result attributes when using cached result."""
# Create mock agent with proper string values
mock_agent = MagicMock()
@@ -694,7 +694,7 @@ def test_tool_usage_finished_event_with_cached_result():
received_events = []
@crewai_event_bus.on(ToolUsageFinishedEvent)
def event_handler(source, event):
def event_handler(source, event) -> None:
received_events.append(event)
# Call on_tool_use_finished with test data and from_cache=True