From f459808c3d6223de1ee9c85b05870e42500e14aa Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Thu, 19 Feb 2026 14:16:07 -0800 Subject: [PATCH] [Fix] Fix flaky tests: spend logs metadata keys, proxy CLI isolation, Redis TTL uniqueness - Add new SpendLogsMetadata keys to ignored_keys in spend logs tests (regression from ccecc10c82 which intentionally includes all keys) - Mock PrismaManager.setup_database and should_update_prisma_schema in proxy CLI tests to prevent real DB migrations from running in CI - Use CliRunner(mix_stderr=False) to fix Click stream lifecycle issues - Use unique UUID suffix for Redis TTL test keys to avoid stale state Co-Authored-By: Claude Opus 4.6 (1M context) --- .../hooks/test_parallel_request_limiter_v3.py | 7 +++-- .../test_spend_management_endpoints.py | 12 ++++++++ tests/test_litellm/proxy/test_proxy_cli.py | 28 +++++++++---------- 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/tests/test_litellm/proxy/hooks/test_parallel_request_limiter_v3.py b/tests/test_litellm/proxy/hooks/test_parallel_request_limiter_v3.py index 134fc84965f..02d51cc4a82 100644 --- a/tests/test_litellm/proxy/hooks/test_parallel_request_limiter_v3.py +++ b/tests/test_litellm/proxy/hooks/test_parallel_request_limiter_v3.py @@ -1176,8 +1176,11 @@ async def test_async_increment_tokens_with_ttl_preservation(): ) # Test keys - use hash tags to ensure they map to same Redis cluster slot - test_key_with_ttl = "{test_ttl}:with_ttl" - test_key_without_ttl = "{test_ttl}:without_ttl" + # Use a unique suffix per test run to avoid stale state from prior runs + import uuid + unique_suffix = str(uuid.uuid4())[:8] + test_key_with_ttl = f"{{test_ttl}}:with_ttl:{unique_suffix}" + test_key_without_ttl = f"{{test_ttl}}:without_ttl:{unique_suffix}" try: # Clean up any existing test keys diff --git a/tests/test_litellm/proxy/spend_tracking/test_spend_management_endpoints.py b/tests/test_litellm/proxy/spend_tracking/test_spend_management_endpoints.py index eabaec8c206..f275681bdef 100644 --- a/tests/test_litellm/proxy/spend_tracking/test_spend_management_endpoints.py +++ b/tests/test_litellm/proxy/spend_tracking/test_spend_management_endpoints.py @@ -287,6 +287,18 @@ ignored_keys = [ "metadata.additional_usage_values.speed", "metadata.litellm_overhead_time_ms", "metadata.cost_breakdown", + "metadata.user_api_key", + "metadata.user_api_key_alias", + "metadata.user_api_key_team_id", + "metadata.user_api_key_project_id", + "metadata.user_api_key_org_id", + "metadata.user_api_key_user_id", + "metadata.user_api_key_team_alias", + "metadata.spend_logs_metadata", + "metadata.requester_ip_address", + "metadata.status", + "metadata.proxy_server_request", + "metadata.error_information", ] MODEL_LIST = [ diff --git a/tests/test_litellm/proxy/test_proxy_cli.py b/tests/test_litellm/proxy/test_proxy_cli.py index 543547943dd..b3cf830ab0c 100644 --- a/tests/test_litellm/proxy/test_proxy_cli.py +++ b/tests/test_litellm/proxy/test_proxy_cli.py @@ -225,13 +225,15 @@ class TestProxyInitializationHelpers: assert modified_url == "" @patch("uvicorn.run") - @patch("atexit.register") # 🔥 critical - def test_skip_server_startup(self, mock_atexit_register, mock_uvicorn_run): + @patch("atexit.register") # critical + @patch("litellm.proxy.db.prisma_client.PrismaManager.setup_database") + @patch("litellm.proxy.db.prisma_client.should_update_prisma_schema", return_value=False) + def test_skip_server_startup(self, mock_should_update, mock_setup_db, mock_atexit_register, mock_uvicorn_run): from click.testing import CliRunner from litellm.proxy.proxy_cli import run_server - runner = CliRunner() + runner = CliRunner(mix_stderr=False) mock_proxy_module = MagicMock( app=MagicMock(), @@ -594,7 +596,7 @@ class TestHealthAppFactory: from litellm.proxy.proxy_cli import run_server - runner = CliRunner() + runner = CliRunner(mix_stderr=False) # Mock subprocess.run to simulate prisma being available mock_subprocess_run.return_value = MagicMock(returncode=0) @@ -602,20 +604,18 @@ class TestHealthAppFactory: # Mock should_update_prisma_schema to return True (so setup_database gets called) mock_should_update_schema.return_value = True - mock_app = MagicMock() - mock_proxy_config = MagicMock() - mock_key_mgmt = MagicMock() - mock_save_worker_config = MagicMock() + mock_proxy_module = MagicMock( + app=MagicMock(), + ProxyConfig=MagicMock(), + KeyManagementSettings=MagicMock(), + save_worker_config=MagicMock(), + ) with patch.dict( "sys.modules", { - "proxy_server": MagicMock( - app=mock_app, - ProxyConfig=mock_proxy_config, - KeyManagementSettings=mock_key_mgmt, - save_worker_config=mock_save_worker_config, - ) + "proxy_server": mock_proxy_module, + "litellm.proxy.proxy_server": mock_proxy_module, }, ), patch( "litellm.proxy.proxy_cli.ProxyInitializationHelpers._get_default_unvicorn_init_args"