Refactor tests to use fixture for better maintainability

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-07 15:03:17 +00:00
parent 237c9504ad
commit 0de31fc775
+50 -39
View File
@@ -1,18 +1,36 @@
""" """
Tests for /processall endpoint throttling behavior. Tests for /processall endpoint throttling behavior.
""" """
import os import os
from unittest.mock import MagicMock, Mock, patch
import pytest import pytest
from unittest.mock import Mock, patch, MagicMock
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@pytest.fixture
def mock_throttle_settings(monkeypatch):
"""Fixture to configure throttle settings for tests."""
def _configure(workdir, threshold=20, delay=3):
from app.api import process
monkeypatch.setattr(process.settings, "workdir", str(workdir))
monkeypatch.setattr(process.settings, "processall_throttle_threshold", threshold)
monkeypatch.setattr(process.settings, "processall_throttle_delay", delay)
return _configure
@pytest.mark.integration @pytest.mark.integration
class TestProcessAllThrottling: class TestProcessAllThrottling:
"""Tests for processall endpoint with throttling.""" """Tests for processall endpoint with throttling."""
@patch('app.api.process.process_document') @patch("app.api.process.process_document")
def test_processall_no_throttling_for_small_batch(self, mock_task, client: TestClient, tmp_path, monkeypatch): def test_processall_no_throttling_for_small_batch(
self, mock_task, client: TestClient, tmp_path, mock_throttle_settings
):
"""Test that small batches (<=20 files) are not throttled.""" """Test that small batches (<=20 files) are not throttled."""
# Create test directory with 10 PDF files # Create test directory with 10 PDF files
workdir = tmp_path / "workdir" workdir = tmp_path / "workdir"
@@ -25,11 +43,8 @@ class TestProcessAllThrottling:
mock_task.delay = Mock(return_value=Mock(id="task-id")) mock_task.delay = Mock(return_value=Mock(id="task-id"))
mock_task.apply_async = Mock(return_value=Mock(id="task-id")) mock_task.apply_async = Mock(return_value=Mock(id="task-id"))
# Use monkeypatch to modify the settings imported in the process module # Configure settings
from app.api import process mock_throttle_settings(workdir, threshold=20, delay=3)
monkeypatch.setattr(process.settings, 'workdir', str(workdir))
monkeypatch.setattr(process.settings, 'processall_throttle_threshold', 20)
monkeypatch.setattr(process.settings, 'processall_throttle_delay', 3)
response = client.post("/api/processall") response = client.post("/api/processall")
@@ -45,8 +60,10 @@ class TestProcessAllThrottling:
assert len(data["pdf_files"]) == 10 assert len(data["pdf_files"]) == 10
assert len(data["task_ids"]) == 10 assert len(data["task_ids"]) == 10
@patch('app.api.process.process_document') @patch("app.api.process.process_document")
def test_processall_throttling_for_large_batch(self, mock_task, client: TestClient, tmp_path, monkeypatch): def test_processall_throttling_for_large_batch(
self, mock_task, client: TestClient, tmp_path, mock_throttle_settings
):
"""Test that large batches (>20 files) are throttled.""" """Test that large batches (>20 files) are throttled."""
# Create test directory with 25 PDF files # Create test directory with 25 PDF files
workdir = tmp_path / "workdir" workdir = tmp_path / "workdir"
@@ -59,10 +76,8 @@ class TestProcessAllThrottling:
mock_task_result = Mock(id="task-id") mock_task_result = Mock(id="task-id")
mock_task.apply_async = Mock(return_value=mock_task_result) mock_task.apply_async = Mock(return_value=mock_task_result)
from app.api import process # Configure settings
monkeypatch.setattr(process.settings, 'workdir', str(workdir)) mock_throttle_settings(workdir, threshold=20, delay=3)
monkeypatch.setattr(process.settings, 'processall_throttle_threshold', 20)
monkeypatch.setattr(process.settings, 'processall_throttle_delay', 3)
response = client.post("/api/processall") response = client.post("/api/processall")
@@ -76,7 +91,7 @@ class TestProcessAllThrottling:
calls = mock_task.apply_async.call_args_list calls = mock_task.apply_async.call_args_list
for i, call_args in enumerate(calls): for i, call_args in enumerate(calls):
expected_countdown = i * 3 # 3 seconds delay expected_countdown = i * 3 # 3 seconds delay
assert call_args[1]['countdown'] == expected_countdown assert call_args[1]["countdown"] == expected_countdown
# Response should indicate throttling # Response should indicate throttling
assert data["throttled"] is True assert data["throttled"] is True
@@ -84,8 +99,8 @@ class TestProcessAllThrottling:
assert len(data["task_ids"]) == 25 assert len(data["task_ids"]) == 25
assert "throttled over" in data["message"] assert "throttled over" in data["message"]
@patch('app.api.process.process_document') @patch("app.api.process.process_document")
def test_processall_exactly_at_threshold(self, mock_task, client: TestClient, tmp_path, monkeypatch): def test_processall_exactly_at_threshold(self, mock_task, client: TestClient, tmp_path, mock_throttle_settings):
"""Test behavior when file count equals threshold.""" """Test behavior when file count equals threshold."""
# Create test directory with exactly 20 PDF files # Create test directory with exactly 20 PDF files
workdir = tmp_path / "workdir" workdir = tmp_path / "workdir"
@@ -97,10 +112,8 @@ class TestProcessAllThrottling:
# Mock the task # Mock the task
mock_task.delay = Mock(return_value=Mock(id="task-id")) mock_task.delay = Mock(return_value=Mock(id="task-id"))
from app.api import process # Configure settings
monkeypatch.setattr(process.settings, 'workdir', str(workdir)) mock_throttle_settings(workdir, threshold=20, delay=3)
monkeypatch.setattr(process.settings, 'processall_throttle_threshold', 20)
monkeypatch.setattr(process.settings, 'processall_throttle_delay', 3)
response = client.post("/api/processall") response = client.post("/api/processall")
@@ -111,8 +124,8 @@ class TestProcessAllThrottling:
assert mock_task.delay.call_count == 20 assert mock_task.delay.call_count == 20
assert data["throttled"] is False assert data["throttled"] is False
@patch('app.api.process.process_document') @patch("app.api.process.process_document")
def test_processall_one_over_threshold(self, mock_task, client: TestClient, tmp_path, monkeypatch): def test_processall_one_over_threshold(self, mock_task, client: TestClient, tmp_path, mock_throttle_settings):
"""Test that throttling activates at threshold + 1.""" """Test that throttling activates at threshold + 1."""
# Create test directory with 21 PDF files (threshold is 20) # Create test directory with 21 PDF files (threshold is 20)
workdir = tmp_path / "workdir" workdir = tmp_path / "workdir"
@@ -124,10 +137,8 @@ class TestProcessAllThrottling:
# Mock the task # Mock the task
mock_task.apply_async = Mock(return_value=Mock(id="task-id")) mock_task.apply_async = Mock(return_value=Mock(id="task-id"))
from app.api import process # Configure settings
monkeypatch.setattr(process.settings, 'workdir', str(workdir)) mock_throttle_settings(workdir, threshold=20, delay=3)
monkeypatch.setattr(process.settings, 'processall_throttle_threshold', 20)
monkeypatch.setattr(process.settings, 'processall_throttle_delay', 3)
response = client.post("/api/processall") response = client.post("/api/processall")
@@ -138,13 +149,13 @@ class TestProcessAllThrottling:
assert mock_task.apply_async.call_count == 21 assert mock_task.apply_async.call_count == 21
assert data["throttled"] is True assert data["throttled"] is True
def test_processall_empty_directory(self, client: TestClient, tmp_path, monkeypatch): def test_processall_empty_directory(self, client: TestClient, tmp_path, mock_throttle_settings):
"""Test processall with no PDF files.""" """Test processall with no PDF files."""
workdir = tmp_path / "workdir" workdir = tmp_path / "workdir"
workdir.mkdir() workdir.mkdir()
from app.api import process # Configure settings
monkeypatch.setattr(process.settings, 'workdir', str(workdir)) mock_throttle_settings(workdir)
response = client.post("/api/processall") response = client.post("/api/processall")
@@ -152,12 +163,12 @@ class TestProcessAllThrottling:
data = response.json() data = response.json()
assert data["message"] == "No PDF files found in that directory." assert data["message"] == "No PDF files found in that directory."
def test_processall_nonexistent_directory(self, client: TestClient, tmp_path, monkeypatch): def test_processall_nonexistent_directory(self, client: TestClient, tmp_path, mock_throttle_settings):
"""Test processall with non-existent directory.""" """Test processall with non-existent directory."""
workdir = tmp_path / "nonexistent" workdir = tmp_path / "nonexistent"
from app.api import process # Configure settings
monkeypatch.setattr(process.settings, 'workdir', str(workdir)) mock_throttle_settings(workdir)
response = client.post("/api/processall") response = client.post("/api/processall")
@@ -165,8 +176,8 @@ class TestProcessAllThrottling:
data = response.json() data = response.json()
assert "does not exist" in data["detail"] assert "does not exist" in data["detail"]
@patch('app.api.process.process_document') @patch("app.api.process.process_document")
def test_processall_custom_threshold(self, mock_task, client: TestClient, tmp_path, monkeypatch): def test_processall_custom_threshold(self, mock_task, client: TestClient, tmp_path, mock_throttle_settings):
"""Test that custom threshold value is respected.""" """Test that custom threshold value is respected."""
# Create test directory with 15 PDF files # Create test directory with 15 PDF files
workdir = tmp_path / "workdir" workdir = tmp_path / "workdir"
@@ -178,10 +189,8 @@ class TestProcessAllThrottling:
# Mock the task # Mock the task
mock_task.apply_async = Mock(return_value=Mock(id="task-id")) mock_task.apply_async = Mock(return_value=Mock(id="task-id"))
from app.api import process # Configure settings with lower threshold
monkeypatch.setattr(process.settings, 'workdir', str(workdir)) mock_throttle_settings(workdir, threshold=10, delay=2)
monkeypatch.setattr(process.settings, 'processall_throttle_threshold', 10) # Lower threshold
monkeypatch.setattr(process.settings, 'processall_throttle_delay', 2)
response = client.post("/api/processall") response = client.post("/api/processall")
@@ -200,6 +209,7 @@ class TestThrottlingConfiguration:
def test_default_throttle_threshold(self): def test_default_throttle_threshold(self):
"""Test that default threshold is 20.""" """Test that default threshold is 20."""
from app.config import Settings from app.config import Settings
settings = Settings( settings = Settings(
database_url="sqlite:///test.db", database_url="sqlite:///test.db",
redis_url="redis://localhost", redis_url="redis://localhost",
@@ -216,6 +226,7 @@ class TestThrottlingConfiguration:
def test_default_throttle_delay(self): def test_default_throttle_delay(self):
"""Test that default delay is 3 seconds.""" """Test that default delay is 3 seconds."""
from app.config import Settings from app.config import Settings
settings = Settings( settings = Settings(
database_url="sqlite:///test.db", database_url="sqlite:///test.db",
redis_url="redis://localhost", redis_url="redis://localhost",