diff --git a/backend/tests/agent/test_checklist_verifier.py b/backend/tests/agent/test_checklist_verifier.py index 37cfe87e1..2271e1bd7 100644 --- a/backend/tests/agent/test_checklist_verifier.py +++ b/backend/tests/agent/test_checklist_verifier.py @@ -1,9 +1,11 @@ import unittest from unittest.mock import MagicMock, patch + from agent.nodes import checklist_verifier from agent.state import OverallState + class TestChecklistVerifier(unittest.TestCase): def setUp(self): self.mock_config = {"configurable": {"thread_id": "1", "answer_model": "test-model"}} diff --git a/backend/tests/agent/test_middleware_security.py b/backend/tests/agent/test_middleware_security.py index d9c0dd6a6..0de1fb072 100644 --- a/backend/tests/agent/test_middleware_security.py +++ b/backend/tests/agent/test_middleware_security.py @@ -1,8 +1,10 @@ -import pytest from unittest.mock import MagicMock -from fastapi.testclient import TestClient + +import pytest from fastapi import Request, Response -from agent.app import app, ContentSizeLimitMiddleware +from fastapi.testclient import TestClient + +from agent.app import ContentSizeLimitMiddleware, app # Initialize TestClient with a trusted host (localhost) to pass TrustedHostMiddleware client = TestClient(app, base_url="http://localhost") diff --git a/backend/tests/agent/test_orchestration.py b/backend/tests/agent/test_orchestration.py index 9285b9f8a..0222940e7 100644 --- a/backend/tests/agent/test_orchestration.py +++ b/backend/tests/agent/test_orchestration.py @@ -7,22 +7,22 @@ - Orchestrated graph construction """ +from typing import Any, Dict +from unittest.mock import AsyncMock, MagicMock, patch + import pytest -from unittest.mock import MagicMock, patch, AsyncMock -from typing import Dict, Any +from langchain_core.messages import AIMessage, HumanMessage from agent.orchestration import ( - ToolRegistry, AgentPool, - ToolSpec, AgentSpec, + ToolRegistry, + ToolSpec, + build_orchestrated_graph, create_coordinator_node, create_task_router, - build_orchestrated_graph, ) from agent.state import OverallState -from langchain_core.messages import HumanMessage, AIMessage - # ============================================================================= # ToolRegistry Tests diff --git a/backend/tests/agent/test_rag.py b/backend/tests/agent/test_rag.py index 30c63fd2e..6e5a26a93 100644 --- a/backend/tests/agent/test_rag.py +++ b/backend/tests/agent/test_rag.py @@ -1,9 +1,11 @@ -import pytest +import importlib import sys -import numpy as np from unittest.mock import MagicMock, patch -import importlib + +import numpy as np +import pytest + # Fixture to mock dependencies before importing the module under test @pytest.fixture diff --git a/backend/tests/agent/test_rate_limiter.py b/backend/tests/agent/test_rate_limiter.py index efc333959..7bd68851e 100644 --- a/backend/tests/agent/test_rate_limiter.py +++ b/backend/tests/agent/test_rate_limiter.py @@ -1,10 +1,12 @@ """Tests for RateLimiter.""" import unittest +from datetime import date, datetime, timedelta from unittest.mock import MagicMock, patch -from datetime import datetime, date, timedelta from zoneinfo import ZoneInfo -from agent.rate_limiter import RateLimiter, PACIFIC_TZ + +from agent.rate_limiter import PACIFIC_TZ, RateLimiter + class TestRateLimiter(unittest.TestCase): def test_daily_reset_logic(self): diff --git a/backend/tests/agent/test_rate_limiter_proxy.py b/backend/tests/agent/test_rate_limiter_proxy.py index 860ce6627..1b509f7c7 100644 --- a/backend/tests/agent/test_rate_limiter_proxy.py +++ b/backend/tests/agent/test_rate_limiter_proxy.py @@ -1,9 +1,11 @@ +from unittest.mock import patch + import pytest from fastapi.testclient import TestClient -from unittest.mock import patch +from starlette.responses import PlainTextResponse + from agent.app import app from agent.security import RateLimitMiddleware -from starlette.responses import PlainTextResponse # ---------------------------------------------------------------------- # 1. Integration Test with FastAPI App diff --git a/backend/tests/agent/test_supervisor_llm.py b/backend/tests/agent/test_supervisor_llm.py index 0b4f2087d..dc013b793 100644 --- a/backend/tests/agent/test_supervisor_llm.py +++ b/backend/tests/agent/test_supervisor_llm.py @@ -1,11 +1,14 @@ -import pytest -from unittest.mock import patch, MagicMock import dataclasses -from agent.state import OverallState +from unittest.mock import MagicMock, patch + +import pytest +from langchain_core.messages import AIMessage +from langchain_core.runnables import RunnableConfig + from agent.graphs import supervisor from agent.graphs.supervisor import compress_context -from langchain_core.runnables import RunnableConfig -from langchain_core.messages import AIMessage +from agent.state import OverallState + @pytest.fixture def enable_compression(): diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py index cc8f91187..baa7353c6 100644 --- a/backend/tests/conftest.py +++ b/backend/tests/conftest.py @@ -3,13 +3,13 @@ This module provides reusable fixtures that can be used across all test files. Fixtures are designed to be path-insensitive and robust to minor code changes. """ +import os import pathlib import sys -from typing import Any, Dict, List from types import SimpleNamespace +from typing import Any, Dict, List import pytest -import os # Set dummy API key before any imports that might use it os.environ["GEMINI_API_KEY"] = "dummy_key_for_tests" diff --git a/backend/tests/evaluators.py b/backend/tests/evaluators.py index 804485bcf..1721639d8 100644 --- a/backend/tests/evaluators.py +++ b/backend/tests/evaluators.py @@ -4,12 +4,14 @@ structured grading of agent outputs using a Judge LLM (Gemini 2.5 Pro). """ -from typing import Dict, Any, Optional, List -from pydantic import BaseModel, Field -from langchain_google_genai import ChatGoogleGenerativeAI +import os +from typing import Any, Dict, List, Optional + from langchain_core.prompts import ChatPromptTemplate +from langchain_google_genai import ChatGoogleGenerativeAI +from pydantic import BaseModel, Field + from agent.models import GEMINI_PRO -import os # Module-level cache for the judge model instance _judge_model_cache: Optional[ChatGoogleGenerativeAI] = None diff --git a/backend/tests/test_configuration.py b/backend/tests/test_configuration.py index f394cc5f2..094cd83ab 100644 --- a/backend/tests/test_configuration.py +++ b/backend/tests/test_configuration.py @@ -8,11 +8,11 @@ from agent.configuration import Configuration from agent.models import ( - TEST_MODEL, - GEMINI_PRO, + DEFAULT_ANSWER_MODEL, DEFAULT_QUERY_MODEL, DEFAULT_REFLECTION_MODEL, - DEFAULT_ANSWER_MODEL, + GEMINI_PRO, + TEST_MODEL, ) diff --git a/backend/tests/test_gemma_compatibility.py b/backend/tests/test_gemma_compatibility.py index e561d4d9c..1ebdf00d6 100644 --- a/backend/tests/test_gemma_compatibility.py +++ b/backend/tests/test_gemma_compatibility.py @@ -7,16 +7,17 @@ 3. Robustness against token limit behaviors typical of smaller models. """ +from unittest.mock import ANY, MagicMock, patch + import pytest -from unittest.mock import MagicMock, patch, ANY -from langchain_core.runnables import RunnableConfig from langchain_core.messages import AIMessage, HumanMessage +from langchain_core.runnables import RunnableConfig from agent.models import GEMMA_2_27B_IT, GEMMA_3_27B_IT from agent.nodes import ( + denoising_refiner, generate_plan, web_research, - denoising_refiner, ) from agent.state import OverallState diff --git a/backend/tests/test_graph_mock.py b/backend/tests/test_graph_mock.py index a1d1f9bbf..770e66cb7 100644 --- a/backend/tests/test_graph_mock.py +++ b/backend/tests/test_graph_mock.py @@ -1,8 +1,16 @@ +from unittest.mock import MagicMock, Mock, patch + import pytest -from unittest.mock import Mock, patch, MagicMock -from agent.nodes import generate_plan, web_research, reflection, denoising_refiner, load_context -from langchain_core.messages import HumanMessage, AIMessage +from langchain_core.messages import AIMessage, HumanMessage + from agent.models import TEST_MODEL +from agent.nodes import ( + denoising_refiner, + generate_plan, + load_context, + reflection, + web_research, +) TEST_MODEL = "gemma-3-27b-it" diff --git a/backend/tests/test_input_validation.py b/backend/tests/test_input_validation.py index 4baf043d0..32708b750 100644 --- a/backend/tests/test_input_validation.py +++ b/backend/tests/test_input_validation.py @@ -1,12 +1,13 @@ -import unittest -import sys import os +import sys +import unittest # Add backend/src to python path sys.path.append(os.path.join(os.path.dirname(__file__), "../src")) from agent.app import InvokeRequest + class TestDoS(unittest.TestCase): def test_large_initial_query_count(self): """ diff --git a/backend/tests/test_ipv6_rate_limit.py b/backend/tests/test_ipv6_rate_limit.py index da5fa3fc7..a9315b04e 100644 --- a/backend/tests/test_ipv6_rate_limit.py +++ b/backend/tests/test_ipv6_rate_limit.py @@ -1,8 +1,11 @@ +from unittest.mock import AsyncMock, MagicMock + import pytest -from unittest.mock import MagicMock, AsyncMock + from agent.security import RateLimitMiddleware + class MockApp: pass diff --git a/backend/tests/test_kaggle_integration.py b/backend/tests/test_kaggle_integration.py index f0122b3c8..894bc155f 100644 --- a/backend/tests/test_kaggle_integration.py +++ b/backend/tests/test_kaggle_integration.py @@ -3,9 +3,16 @@ Unit tests for backend/examples/kaggle_integration.py """ +from unittest.mock import MagicMock, patch + import pytest -from unittest.mock import patch, MagicMock -from examples.kaggle_integration import KaggleModelLoader, KaggleHuggingFaceClient, SimpleReActAgent, BaseLLMClient + +from examples.kaggle_integration import ( + BaseLLMClient, + KaggleHuggingFaceClient, + KaggleModelLoader, + SimpleReActAgent, +) # ============================================================================= # Tests for KaggleModelLoader diff --git a/backend/tests/test_mcp.py b/backend/tests/test_mcp.py index 150580cec..4d93cfee3 100644 --- a/backend/tests/test_mcp.py +++ b/backend/tests/test_mcp.py @@ -1,5 +1,7 @@ +from unittest.mock import AsyncMock, MagicMock, patch + import pytest -from unittest.mock import MagicMock, patch, AsyncMock + from agent.tools_and_schemas import get_tools_from_mcp # Fine-grained implementation guide for MCP Tests: diff --git a/backend/tests/test_mcp_config.py b/backend/tests/test_mcp_config.py index bb22fbe7f..b6a96bf8f 100644 --- a/backend/tests/test_mcp_config.py +++ b/backend/tests/test_mcp_config.py @@ -1,7 +1,9 @@ import os import unittest from unittest import mock -from agent.mcp_config import load_mcp_settings, validate, MCPSettings + +from agent.mcp_config import MCPSettings, load_mcp_settings, validate + class TestMCPSettings(unittest.TestCase): def test_default_settings(self): diff --git a/backend/tests/test_mcp_tools.py b/backend/tests/test_mcp_tools.py index 1d51f4e93..33f0f92a2 100644 --- a/backend/tests/test_mcp_tools.py +++ b/backend/tests/test_mcp_tools.py @@ -1,8 +1,11 @@ import asyncio -import pytest from unittest.mock import MagicMock, patch -from agent.tools_and_schemas import get_tools_from_mcp + +import pytest + from agent.mcp_config import MCPSettings +from agent.tools_and_schemas import get_tools_from_mcp + @pytest.mark.asyncio async def test_get_tools_from_mcp_disabled(): diff --git a/backend/tests/test_memory_tools.py b/backend/tests/test_memory_tools.py index 43a26729a..b603766f3 100644 --- a/backend/tests/test_memory_tools.py +++ b/backend/tests/test_memory_tools.py @@ -1,8 +1,10 @@ -import unittest -from agent.memory_tools import save_plan_tool, load_plan_tool -from agent.persistence import PLAN_DIR import os import shutil +import unittest + +from agent.memory_tools import load_plan_tool, save_plan_tool +from agent.persistence import PLAN_DIR + class TestMemoryTools(unittest.TestCase): def setUp(self): diff --git a/backend/tests/test_nodes.py b/backend/tests/test_nodes.py index eafb5ee3b..9e009d576 100644 --- a/backend/tests/test_nodes.py +++ b/backend/tests/test_nodes.py @@ -12,28 +12,30 @@ - Edge cases and error handling """ -import pytest import dataclasses -from unittest.mock import Mock, patch, MagicMock, AsyncMock -from langchain_core.runnables import RunnableConfig +from unittest.mock import AsyncMock, MagicMock, Mock, patch + +import pytest from langchain_core.messages import AIMessage, HumanMessage +from langchain_core.runnables import RunnableConfig -from config.app_config import AppConfig, config as real_config -from agent.state import OverallState from agent import nodes +from agent.models import TEST_MODEL from agent.nodes import ( + content_reader, + denoising_refiner, + execution_router, generate_plan, planning_mode, planning_wait, - web_research, - validate_web_results, reflection, - denoising_refiner, - content_reader, select_next_task, - execution_router, + validate_web_results, + web_research, ) -from agent.models import TEST_MODEL +from agent.state import OverallState +from config.app_config import AppConfig +from config.app_config import config as real_config # Fixtures diff --git a/backend/tests/test_persistence.py b/backend/tests/test_persistence.py index 4b600c297..192cc64ce 100644 --- a/backend/tests/test_persistence.py +++ b/backend/tests/test_persistence.py @@ -5,6 +5,7 @@ """ import json import os + import pytest diff --git a/backend/tests/test_planning.py b/backend/tests/test_planning.py index 1b86c82a2..fa4a7d62b 100644 --- a/backend/tests/test_planning.py +++ b/backend/tests/test_planning.py @@ -4,8 +4,8 @@ state configurations and flags. """ import pytest -from agent.nodes import planning_mode, planning_router, planning_wait +from agent.nodes import planning_mode, planning_router, planning_wait # ============================================================================= # Helper function diff --git a/backend/tests/test_proxy_security.py b/backend/tests/test_proxy_security.py index da67a60ff..6d3855f0d 100644 --- a/backend/tests/test_proxy_security.py +++ b/backend/tests/test_proxy_security.py @@ -1,9 +1,12 @@ +from unittest.mock import AsyncMock, MagicMock + import pytest -from unittest.mock import MagicMock, AsyncMock from starlette.responses import PlainTextResponse + from agent.security import RateLimitMiddleware + @pytest.mark.asyncio async def test_proxy_security_default_secure(): """Verify that by default (trust_proxy_headers=False), X-Forwarded-For is ignored.""" diff --git a/backend/tests/test_rag_nodes_mock.py b/backend/tests/test_rag_nodes_mock.py index 4ac8b3008..a3b708696 100644 --- a/backend/tests/test_rag_nodes_mock.py +++ b/backend/tests/test_rag_nodes_mock.py @@ -1,7 +1,10 @@ -import pytest from unittest.mock import Mock, patch + +import pytest + from agent.rag_nodes import rag_retrieve + @pytest.fixture def mock_rag_state(): return { diff --git a/backend/tests/test_registry.py b/backend/tests/test_registry.py index ec65d4ad5..3b449e223 100644 --- a/backend/tests/test_registry.py +++ b/backend/tests/test_registry.py @@ -10,6 +10,7 @@ """ import pytest + from agent.registry import GraphRegistry, graph_registry diff --git a/backend/tests/test_research_tools.py b/backend/tests/test_research_tools.py index af24d7c12..b965842db 100644 --- a/backend/tests/test_research_tools.py +++ b/backend/tests/test_research_tools.py @@ -2,8 +2,10 @@ Tests cover search functions, summarization, deduplication, and tool definitions. """ +from unittest.mock import MagicMock, Mock, patch + import pytest -from unittest.mock import Mock, patch, MagicMock + from agent.models import GEMINI_FLASH, GEMINI_PRO diff --git a/backend/tests/test_search_robustness.py b/backend/tests/test_search_robustness.py index 4e35f39bf..124341c0a 100644 --- a/backend/tests/test_search_robustness.py +++ b/backend/tests/test_search_robustness.py @@ -4,9 +4,16 @@ These tests ensure that the agent's search tools do not crash when external APIs return unexpected structures, empty strings, or partial data. """ -import pytest from unittest.mock import MagicMock, patch -from agent.research_tools import deduplicate_search_results, process_search_results, format_search_output + +import pytest + +from agent.research_tools import ( + deduplicate_search_results, + format_search_output, + process_search_results, +) + class TestSearchRobustness: diff --git a/backend/tests/test_search_router.py b/backend/tests/test_search_router.py index bd199f46a..203c82561 100644 --- a/backend/tests/test_search_router.py +++ b/backend/tests/test_search_router.py @@ -5,19 +5,19 @@ - Routing logic (primary vs fallback). - Error handling and fallback mechanisms. """ -import pytest -from unittest.mock import MagicMock, patch - # Import SUT import sys -from unittest.mock import MagicMock +from unittest.mock import MagicMock, patch + +import pytest # MOCK google.genai BEFORE importing search.router to avoid broken environment dependencies # (e.g. pycares/aiohttp issues in current env) sys.modules["google.genai"] = MagicMock() -from search.router import SearchRouter, SearchProviderType from search.provider import SearchResult +from search.router import SearchProviderType, SearchRouter + class TestSearchRouter: """Tests for SearchRouter logic.""" diff --git a/backend/tests/test_state.py b/backend/tests/test_state.py index 0f19eb48a..e987aed68 100644 --- a/backend/tests/test_state.py +++ b/backend/tests/test_state.py @@ -8,20 +8,20 @@ - State validation and edge cases """ +from typing import Any, Dict, List + import pytest -from typing import List, Dict, Any from agent.state import ( - create_rag_resources, OverallState, - ReflectionState, Query, QueryGenerationState, - WebSearchState, + ReflectionState, SearchStateOutput, + WebSearchState, + create_rag_resources, ) - # ============================================================================= # Tests for create_rag_resources Function # ============================================================================= diff --git a/backend/tests/test_state_types.py b/backend/tests/test_state_types.py index 41e3cbab6..d8036994c 100644 --- a/backend/tests/test_state_types.py +++ b/backend/tests/test_state_types.py @@ -1,7 +1,10 @@ import json + import pytest + from agent.state import OverallState, Todo, validate_scoping + def test_typing_smoke(): """Ensure OverallState can be instantiated with new fields.""" s: OverallState = { diff --git a/backend/tests/test_supervisor.py b/backend/tests/test_supervisor.py index 68bc4ddce..1500a852e 100644 --- a/backend/tests/test_supervisor.py +++ b/backend/tests/test_supervisor.py @@ -8,21 +8,20 @@ - Graph compilation and structure """ -import pytest -from unittest.mock import patch, MagicMock -from typing import Dict, Any -from langchain_core.runnables import RunnableConfig - -from agent.state import OverallState -from agent.graphs.supervisor import compress_context, graph - - # ============================================================================= # Fixtures # ============================================================================= - import dataclasses +from typing import Any, Dict +from unittest.mock import MagicMock, patch + +import pytest +from langchain_core.runnables import RunnableConfig + from agent.graphs import supervisor +from agent.graphs.supervisor import compress_context, graph +from agent.state import OverallState + @pytest.fixture(autouse=True) def disable_compression(): diff --git a/backend/tests/test_utils.py b/backend/tests/test_utils.py index ff3902bf4..e6661c448 100644 --- a/backend/tests/test_utils.py +++ b/backend/tests/test_utils.py @@ -3,13 +3,20 @@ Tests cover edge cases, error handling, and typical usage patterns. All tests are designed to be path-insensitive and robust to minor changes. """ -import pytest from typing import List +import pytest +from langchain_core.messages import AIMessage, HumanMessage + from tests.helpers import ( - MockSegment, MockChunk, MockSupport, MockCandidate, MockResponse, MockSite + MockCandidate, + MockChunk, + MockResponse, + MockSegment, + MockSite, + MockSupport, ) -from langchain_core.messages import HumanMessage, AIMessage + def make_human_message(content): return HumanMessage(content=content) @@ -17,13 +24,12 @@ def make_human_message(content): def make_ai_message(content): return AIMessage(content=content) from agent.utils import ( + get_citations, get_research_topic, - resolve_urls, insert_citation_markers, - get_citations, + resolve_urls, ) - # ============================================================================= # Tests for get_research_topic # ============================================================================= @@ -311,6 +317,7 @@ def test_citations_handle_titles_without_dots(self): from agent.utils import join_and_truncate + class TestJoinAndTruncate: """Tests for the join_and_truncate function.""" @@ -385,6 +392,7 @@ def test_limit_cuts_separator_completely(self): from agent.utils import has_fuzzy_match + class TestHasFuzzyMatch: """Tests for the has_fuzzy_match function.""" diff --git a/backend/tests/test_utils_hypothesis.py b/backend/tests/test_utils_hypothesis.py index 65dae94f9..70a10fc73 100644 --- a/backend/tests/test_utils_hypothesis.py +++ b/backend/tests/test_utils_hypothesis.py @@ -1,5 +1,7 @@ -from hypothesis import given, strategies as st, settings, HealthCheck import pytest +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + from agent.utils import insert_citation_markers # Mark these tests as extended because they are slow property-based tests diff --git a/backend/tests/test_validate_web_results.py b/backend/tests/test_validate_web_results.py index 95149d285..2cc5736b8 100644 --- a/backend/tests/test_validate_web_results.py +++ b/backend/tests/test_validate_web_results.py @@ -2,8 +2,9 @@ Tests cover filtering logic, edge cases, and fallback behavior. """ +from unittest.mock import MagicMock, patch + import pytest -from unittest.mock import patch, MagicMock from langchain_core.runnables import RunnableConfig from agent.nodes import validate_web_results diff --git a/backend/tests/test_validation.py b/backend/tests/test_validation.py index d9394ac22..3b9fb4624 100644 --- a/backend/tests/test_validation.py +++ b/backend/tests/test_validation.py @@ -1,8 +1,11 @@ +import logging import os +from unittest.mock import MagicMock, patch + import pytest -import logging -from unittest.mock import patch, MagicMock -from config.validation import validate_environment, check_env_strict + +from config.validation import check_env_strict, validate_environment + class TestValidation: diff --git a/backend/tests/test_validation_coverage.py b/backend/tests/test_validation_coverage.py index 0371b75d0..c45b04006 100644 --- a/backend/tests/test_validation_coverage.py +++ b/backend/tests/test_validation_coverage.py @@ -1,9 +1,12 @@ -import os -import logging import importlib.util -from unittest.mock import patch, MagicMock +import logging +import os +from unittest.mock import MagicMock, patch + import pytest -from config.validation import validate_environment, check_env_strict + +from config.validation import check_env_strict, validate_environment + class TestValidation: @pytest.fixture diff --git a/scripts/dev.py b/scripts/dev.py index e035f5ecb..a8cd6fb4c 100644 --- a/scripts/dev.py +++ b/scripts/dev.py @@ -14,7 +14,7 @@ def main(): frontend_dir = os.path.join(root_dir, "frontend") backend_dir = os.path.join(root_dir, "backend") - print(f"🚀 Starting development servers...") + print("🚀 Starting development servers...") # Define commands based on OS is_windows = sys.platform.startswith('win') diff --git a/scripts/generate_sample_reports.py b/scripts/generate_sample_reports.py index ef3a0f7a0..a2b96e4f4 100644 --- a/scripts/generate_sample_reports.py +++ b/scripts/generate_sample_reports.py @@ -113,7 +113,7 @@ async def generate_report(run_config): final_state = await graph.ainvoke(inputs, runnable_config) # Extract Final Answer - if "messages" in final_state and final_state["messages"]: + if final_state.get("messages"): last_msg = final_state["messages"][-1] report_content = last_msg.content else: @@ -130,7 +130,7 @@ async def generate_report(run_config): except Exception as e: print(f"Error generating report for {name}: {e}") - report_content = f"Error generating report: {str(e)}" + report_content = f"Error generating report: {e!s}" import traceback traceback.print_exc()