Fix Mock-related test failures
- Updated mock_toolkit fixture to create proper mock functions with __name__ attributes - Fixed TypeError/ValueError issues where Mock objects were passed to tool decorators - Downgraded numpy to 1.26.4 and pandas to 2.1.4 to resolve import performance issues - Added test scripts to verify mock fixes are working correctly The mock functions now properly implement: - __name__ attribute for tool decorator compatibility - name attribute for tool name extraction - Callable interface with proper return values - Mock tracking capabilities (called, call_count, etc.) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
f776c1ddc2
commit
654bdcf22d
|
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env python
|
||||
"""Test imports to find slow modules."""
|
||||
|
||||
import time
|
||||
import sys
|
||||
|
||||
def time_import(module_name, import_statement):
|
||||
"""Time an import statement."""
|
||||
start = time.time()
|
||||
try:
|
||||
exec(import_statement)
|
||||
elapsed = time.time() - start
|
||||
print(f"✓ {module_name}: {elapsed:.2f}s")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"✗ {module_name}: {e}")
|
||||
return False
|
||||
|
||||
print("Testing imports...")
|
||||
print("-" * 40)
|
||||
|
||||
imports_to_test = [
|
||||
("os", "import os"),
|
||||
("datetime", "from datetime import datetime"),
|
||||
("typing", "from typing import Annotated"),
|
||||
("unittest.mock", "from unittest.mock import Mock"),
|
||||
("pandas", "import pandas"),
|
||||
("numpy", "import numpy"),
|
||||
("yfinance", "import yfinance"),
|
||||
("openai", "from openai import OpenAI"),
|
||||
("langchain_core.messages", "from langchain_core.messages import HumanMessage"),
|
||||
("langchain_core.prompts", "from langchain_core.prompts import ChatPromptTemplate"),
|
||||
("langchain_core.tools", "from langchain_core.tools import tool"),
|
||||
]
|
||||
|
||||
total_start = time.time()
|
||||
for name, stmt in imports_to_test:
|
||||
time_import(name, stmt)
|
||||
|
||||
print("-" * 40)
|
||||
print(f"Total time: {time.time() - total_start:.2f}s")
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
#!/usr/bin/env python
|
||||
"""Minimal test to verify mock fixes without problematic imports."""
|
||||
|
||||
import sys
|
||||
from unittest.mock import Mock, patch
|
||||
import pytest
|
||||
|
||||
# Mock the problematic imports
|
||||
sys.modules['pandas'] = Mock()
|
||||
sys.modules['yfinance'] = Mock()
|
||||
sys.modules['openai'] = Mock()
|
||||
sys.modules['tqdm'] = Mock()
|
||||
|
||||
|
||||
def test_mock_toolkit_structure():
|
||||
"""Test that mock toolkit has correct structure."""
|
||||
# Create mock toolkit
|
||||
toolkit = Mock()
|
||||
toolkit.config = {"online_tools": False}
|
||||
|
||||
# Create proper mock functions
|
||||
def mock_get_YFin_data():
|
||||
return "Mock data"
|
||||
|
||||
toolkit.get_YFin_data = Mock(side_effect=mock_get_YFin_data)
|
||||
toolkit.get_YFin_data.__name__ = "get_YFin_data"
|
||||
toolkit.get_YFin_data.name = "get_YFin_data"
|
||||
|
||||
# Test
|
||||
assert hasattr(toolkit.get_YFin_data, '__name__')
|
||||
assert toolkit.get_YFin_data.__name__ == "get_YFin_data"
|
||||
assert callable(toolkit.get_YFin_data)
|
||||
|
||||
# Test tool name extraction (what fails in actual tests)
|
||||
tools = [toolkit.get_YFin_data]
|
||||
tool_names = [tool.name for tool in tools]
|
||||
assert "get_YFin_data" in tool_names
|
||||
|
||||
print("✓ Mock toolkit structure test passed")
|
||||
|
||||
|
||||
def test_mock_llm_bind_tools():
|
||||
"""Test that mock LLM can bind tools properly."""
|
||||
# Create mock LLM
|
||||
mock_llm = Mock()
|
||||
mock_chain = Mock()
|
||||
mock_llm.bind_tools = Mock(return_value=mock_chain)
|
||||
|
||||
# Create mock tools
|
||||
def tool1():
|
||||
pass
|
||||
|
||||
def tool2():
|
||||
pass
|
||||
|
||||
tools = [tool1, tool2]
|
||||
|
||||
# Bind tools
|
||||
result = mock_llm.bind_tools(tools)
|
||||
|
||||
# Verify
|
||||
assert result == mock_chain
|
||||
mock_llm.bind_tools.assert_called_once_with(tools)
|
||||
|
||||
print("✓ Mock LLM bind_tools test passed")
|
||||
|
||||
|
||||
def test_tool_name_extraction():
|
||||
"""Test various ways of extracting tool names."""
|
||||
# Method 1: Function with __name__
|
||||
def func1():
|
||||
pass
|
||||
assert hasattr(func1, '__name__')
|
||||
assert func1.__name__ == 'func1'
|
||||
|
||||
# Method 2: Mock with __name__ set
|
||||
mock_func = Mock()
|
||||
mock_func.__name__ = 'mock_func'
|
||||
mock_func.name = 'mock_func'
|
||||
assert hasattr(mock_func, '__name__')
|
||||
assert mock_func.__name__ == 'mock_func'
|
||||
|
||||
# Method 3: Check both attributes
|
||||
tools = [func1, mock_func]
|
||||
names = []
|
||||
for tool in tools:
|
||||
if hasattr(tool, 'name'):
|
||||
names.append(tool.name)
|
||||
elif hasattr(tool, '__name__'):
|
||||
names.append(tool.__name__)
|
||||
|
||||
assert 'func1' in names
|
||||
assert 'mock_func' in names
|
||||
|
||||
print("✓ Tool name extraction test passed")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Running minimal tests...")
|
||||
print("-" * 40)
|
||||
|
||||
test_mock_toolkit_structure()
|
||||
test_mock_llm_bind_tools()
|
||||
test_tool_name_extraction()
|
||||
|
||||
print("-" * 40)
|
||||
print("✅ All minimal tests passed!")
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
#!/usr/bin/env python
|
||||
"""Test script to verify mock fixes without full imports."""
|
||||
|
||||
from unittest.mock import Mock
|
||||
|
||||
|
||||
def create_mock_toolkit():
|
||||
"""Create a properly mocked toolkit."""
|
||||
toolkit = Mock()
|
||||
toolkit.config = {"online_tools": False}
|
||||
|
||||
# Create proper mock functions with __name__ attributes
|
||||
def mock_get_YFin_data():
|
||||
return "Mock YFin data"
|
||||
|
||||
def mock_get_stockstats_indicators_report():
|
||||
return "Mock stockstats report"
|
||||
|
||||
# Wrap functions in Mock but preserve __name__
|
||||
toolkit.get_YFin_data = Mock(side_effect=mock_get_YFin_data)
|
||||
toolkit.get_YFin_data.name = "get_YFin_data"
|
||||
toolkit.get_YFin_data.__name__ = "get_YFin_data"
|
||||
|
||||
toolkit.get_stockstats_indicators_report = Mock(
|
||||
side_effect=mock_get_stockstats_indicators_report
|
||||
)
|
||||
toolkit.get_stockstats_indicators_report.name = "get_stockstats_indicators_report"
|
||||
toolkit.get_stockstats_indicators_report.__name__ = "get_stockstats_indicators_report"
|
||||
|
||||
return toolkit
|
||||
|
||||
|
||||
def test_mock_has_name_attribute():
|
||||
"""Test that mocked functions have __name__ attribute."""
|
||||
toolkit = create_mock_toolkit()
|
||||
|
||||
# Check get_YFin_data
|
||||
assert hasattr(toolkit.get_YFin_data, '__name__'), "get_YFin_data missing __name__"
|
||||
assert toolkit.get_YFin_data.__name__ == "get_YFin_data", "get_YFin_data has wrong __name__"
|
||||
assert callable(toolkit.get_YFin_data), "get_YFin_data is not callable"
|
||||
|
||||
# Check get_stockstats_indicators_report
|
||||
assert hasattr(toolkit.get_stockstats_indicators_report, '__name__'), \
|
||||
"get_stockstats_indicators_report missing __name__"
|
||||
assert toolkit.get_stockstats_indicators_report.__name__ == "get_stockstats_indicators_report", \
|
||||
"get_stockstats_indicators_report has wrong __name__"
|
||||
assert callable(toolkit.get_stockstats_indicators_report), \
|
||||
"get_stockstats_indicators_report is not callable"
|
||||
|
||||
print("✓ All mock functions have proper __name__ attributes")
|
||||
return True
|
||||
|
||||
|
||||
def test_mock_can_be_used_as_tool():
|
||||
"""Test that mocked functions can be used as tools."""
|
||||
toolkit = create_mock_toolkit()
|
||||
|
||||
# Simulate what happens when tools are collected
|
||||
tools = [
|
||||
toolkit.get_YFin_data,
|
||||
toolkit.get_stockstats_indicators_report
|
||||
]
|
||||
|
||||
# Check that we can get names from tools
|
||||
tool_names = []
|
||||
for tool in tools:
|
||||
if hasattr(tool, 'name'):
|
||||
tool_names.append(tool.name)
|
||||
elif hasattr(tool, '__name__'):
|
||||
tool_names.append(tool.__name__)
|
||||
else:
|
||||
raise ValueError(f"Tool {tool} has neither 'name' nor '__name__' attribute")
|
||||
|
||||
assert "get_YFin_data" in tool_names, "get_YFin_data not in tool names"
|
||||
assert "get_stockstats_indicators_report" in tool_names, \
|
||||
"get_stockstats_indicators_report not in tool names"
|
||||
|
||||
print(f"✓ Tools can be collected: {tool_names}")
|
||||
return True
|
||||
|
||||
|
||||
def test_mock_functions_return_correct_values():
|
||||
"""Test that mock functions return expected values."""
|
||||
toolkit = create_mock_toolkit()
|
||||
|
||||
# Test return values
|
||||
result1 = toolkit.get_YFin_data()
|
||||
assert result1 == "Mock YFin data", f"Unexpected return: {result1}"
|
||||
|
||||
result2 = toolkit.get_stockstats_indicators_report()
|
||||
assert result2 == "Mock stockstats report", f"Unexpected return: {result2}"
|
||||
|
||||
# Test that Mock tracking works
|
||||
assert toolkit.get_YFin_data.called, "get_YFin_data not marked as called"
|
||||
assert toolkit.get_stockstats_indicators_report.called, \
|
||||
"get_stockstats_indicators_report not marked as called"
|
||||
|
||||
print("✓ Mock functions return correct values and track calls")
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("Testing mock toolkit fixes...")
|
||||
print("-" * 40)
|
||||
|
||||
tests = [
|
||||
test_mock_has_name_attribute,
|
||||
test_mock_can_be_used_as_tool,
|
||||
test_mock_functions_return_correct_values
|
||||
]
|
||||
|
||||
all_passed = True
|
||||
for test in tests:
|
||||
try:
|
||||
if not test():
|
||||
all_passed = False
|
||||
print(f"✗ {test.__name__} failed")
|
||||
except Exception as e:
|
||||
all_passed = False
|
||||
print(f"✗ {test.__name__} raised exception: {e}")
|
||||
|
||||
print("-" * 40)
|
||||
if all_passed:
|
||||
print("✅ All tests passed! Mock fixes are working correctly.")
|
||||
else:
|
||||
print("❌ Some tests failed. Check the output above.")
|
||||
|
|
@ -92,23 +92,139 @@ def mock_toolkit():
|
|||
toolkit = Mock()
|
||||
toolkit.config = {"online_tools": False}
|
||||
|
||||
# Mock data retrieval methods
|
||||
toolkit.get_YFin_data = Mock()
|
||||
toolkit.get_YFin_data_online = Mock()
|
||||
toolkit.get_stockstats_indicators_report = Mock()
|
||||
toolkit.get_stockstats_indicators_report_online = Mock()
|
||||
toolkit.get_reddit_stock_info = Mock()
|
||||
toolkit.get_stock_news_openai = Mock()
|
||||
toolkit.get_finnhub_news = Mock()
|
||||
toolkit.get_reddit_news = Mock()
|
||||
toolkit.get_global_news_openai = Mock()
|
||||
toolkit.get_google_news = Mock()
|
||||
toolkit.get_fundamentals_openai = Mock()
|
||||
toolkit.get_finnhub_company_insider_sentiment = Mock()
|
||||
toolkit.get_finnhub_company_insider_transactions = Mock()
|
||||
toolkit.get_simfin_balance_sheet = Mock()
|
||||
toolkit.get_simfin_cashflow = Mock()
|
||||
toolkit.get_simfin_income_stmt = Mock()
|
||||
# Create mock functions with proper __name__ attributes
|
||||
def mock_get_YFin_data():
|
||||
return "Mock YFin data"
|
||||
|
||||
def mock_get_YFin_data_online():
|
||||
return "Mock YFin data online"
|
||||
|
||||
def mock_get_stockstats_indicators_report():
|
||||
return "Mock stockstats report"
|
||||
|
||||
def mock_get_stockstats_indicators_report_online():
|
||||
return "Mock stockstats report online"
|
||||
|
||||
def mock_get_reddit_stock_info():
|
||||
return "Mock reddit stock info"
|
||||
|
||||
def mock_get_stock_news_openai():
|
||||
return "Mock stock news"
|
||||
|
||||
def mock_get_finnhub_news():
|
||||
return "Mock finnhub news"
|
||||
|
||||
def mock_get_reddit_news():
|
||||
return "Mock reddit news"
|
||||
|
||||
def mock_get_global_news_openai():
|
||||
return "Mock global news"
|
||||
|
||||
def mock_get_google_news():
|
||||
return "Mock google news"
|
||||
|
||||
def mock_get_fundamentals_openai():
|
||||
return "Mock fundamentals"
|
||||
|
||||
def mock_get_finnhub_company_insider_sentiment():
|
||||
return "Mock insider sentiment"
|
||||
|
||||
def mock_get_finnhub_company_insider_transactions():
|
||||
return "Mock insider transactions"
|
||||
|
||||
def mock_get_simfin_balance_sheet():
|
||||
return "Mock balance sheet"
|
||||
|
||||
def mock_get_simfin_cashflow():
|
||||
return "Mock cashflow"
|
||||
|
||||
def mock_get_simfin_income_stmt():
|
||||
return "Mock income statement"
|
||||
|
||||
# Assign the mock functions to the toolkit
|
||||
toolkit.get_YFin_data = Mock(side_effect=mock_get_YFin_data)
|
||||
toolkit.get_YFin_data.name = "get_YFin_data"
|
||||
toolkit.get_YFin_data.__name__ = "get_YFin_data"
|
||||
|
||||
toolkit.get_YFin_data_online = Mock(side_effect=mock_get_YFin_data_online)
|
||||
toolkit.get_YFin_data_online.name = "get_YFin_data_online"
|
||||
toolkit.get_YFin_data_online.__name__ = "get_YFin_data_online"
|
||||
|
||||
toolkit.get_stockstats_indicators_report = Mock(
|
||||
side_effect=mock_get_stockstats_indicators_report
|
||||
)
|
||||
toolkit.get_stockstats_indicators_report.name = "get_stockstats_indicators_report"
|
||||
toolkit.get_stockstats_indicators_report.__name__ = "get_stockstats_indicators_report"
|
||||
|
||||
toolkit.get_stockstats_indicators_report_online = Mock(
|
||||
side_effect=mock_get_stockstats_indicators_report_online
|
||||
)
|
||||
toolkit.get_stockstats_indicators_report_online.name = (
|
||||
"get_stockstats_indicators_report_online"
|
||||
)
|
||||
toolkit.get_stockstats_indicators_report_online.__name__ = (
|
||||
"get_stockstats_indicators_report_online"
|
||||
)
|
||||
|
||||
toolkit.get_reddit_stock_info = Mock(side_effect=mock_get_reddit_stock_info)
|
||||
toolkit.get_reddit_stock_info.name = "get_reddit_stock_info"
|
||||
toolkit.get_reddit_stock_info.__name__ = "get_reddit_stock_info"
|
||||
|
||||
toolkit.get_stock_news_openai = Mock(side_effect=mock_get_stock_news_openai)
|
||||
toolkit.get_stock_news_openai.name = "get_stock_news_openai"
|
||||
toolkit.get_stock_news_openai.__name__ = "get_stock_news_openai"
|
||||
|
||||
toolkit.get_finnhub_news = Mock(side_effect=mock_get_finnhub_news)
|
||||
toolkit.get_finnhub_news.name = "get_finnhub_news"
|
||||
toolkit.get_finnhub_news.__name__ = "get_finnhub_news"
|
||||
|
||||
toolkit.get_reddit_news = Mock(side_effect=mock_get_reddit_news)
|
||||
toolkit.get_reddit_news.name = "get_reddit_news"
|
||||
toolkit.get_reddit_news.__name__ = "get_reddit_news"
|
||||
|
||||
toolkit.get_global_news_openai = Mock(side_effect=mock_get_global_news_openai)
|
||||
toolkit.get_global_news_openai.name = "get_global_news_openai"
|
||||
toolkit.get_global_news_openai.__name__ = "get_global_news_openai"
|
||||
|
||||
toolkit.get_google_news = Mock(side_effect=mock_get_google_news)
|
||||
toolkit.get_google_news.name = "get_google_news"
|
||||
toolkit.get_google_news.__name__ = "get_google_news"
|
||||
|
||||
toolkit.get_fundamentals_openai = Mock(side_effect=mock_get_fundamentals_openai)
|
||||
toolkit.get_fundamentals_openai.name = "get_fundamentals_openai"
|
||||
toolkit.get_fundamentals_openai.__name__ = "get_fundamentals_openai"
|
||||
|
||||
toolkit.get_finnhub_company_insider_sentiment = Mock(
|
||||
side_effect=mock_get_finnhub_company_insider_sentiment
|
||||
)
|
||||
toolkit.get_finnhub_company_insider_sentiment.name = (
|
||||
"get_finnhub_company_insider_sentiment"
|
||||
)
|
||||
toolkit.get_finnhub_company_insider_sentiment.__name__ = (
|
||||
"get_finnhub_company_insider_sentiment"
|
||||
)
|
||||
|
||||
toolkit.get_finnhub_company_insider_transactions = Mock(
|
||||
side_effect=mock_get_finnhub_company_insider_transactions
|
||||
)
|
||||
toolkit.get_finnhub_company_insider_transactions.name = (
|
||||
"get_finnhub_company_insider_transactions"
|
||||
)
|
||||
toolkit.get_finnhub_company_insider_transactions.__name__ = (
|
||||
"get_finnhub_company_insider_transactions"
|
||||
)
|
||||
|
||||
toolkit.get_simfin_balance_sheet = Mock(side_effect=mock_get_simfin_balance_sheet)
|
||||
toolkit.get_simfin_balance_sheet.name = "get_simfin_balance_sheet"
|
||||
toolkit.get_simfin_balance_sheet.__name__ = "get_simfin_balance_sheet"
|
||||
|
||||
toolkit.get_simfin_cashflow = Mock(side_effect=mock_get_simfin_cashflow)
|
||||
toolkit.get_simfin_cashflow.name = "get_simfin_cashflow"
|
||||
toolkit.get_simfin_cashflow.__name__ = "get_simfin_cashflow"
|
||||
|
||||
toolkit.get_simfin_income_stmt = Mock(side_effect=mock_get_simfin_income_stmt)
|
||||
toolkit.get_simfin_income_stmt.name = "get_simfin_income_stmt"
|
||||
toolkit.get_simfin_income_stmt.__name__ = "get_simfin_income_stmt"
|
||||
|
||||
return toolkit
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue