litellm/tests/test_litellm/proxy/client/test_client.py
Yuneng Jiang ff4120863b
test: rename tests that a later definition shadowed
Python keeps only the last binding for a name, so when a file defines the same
test twice the earlier one is unreachable. pytest cannot collect a function that
no longer exists, so nothing reports it and the file still looks like it covers
the scenario.

These ten are cases where the two definitions have different bodies, meaning a
real test was replaced rather than duplicated. Each is renamed to say what it
actually covers, which makes it reachable again:

- test_gemini_frequency_penalty: the dead copy checks the parameter is listed in
  get_supported_openai_params for vertex_ai; the survivor checks get_optional_params
  maps a value for gemini. Different function and different provider.
- test_async_log_success_event_adds_to_queue and the failure variant: the dead
  copies run without mocking asyncio.create_task, so they exercise the real task
  path the survivors mock out.
- test_async_send_batch_triggers_tasks: the dead copy asserts send is not awaited
  directly; the survivor asserts create_task was called.
- test_model_id_in_required_metrics: the dead copy checks the model_id label on
  twelve further metrics the survivor dropped.
- test_anthropic_messages_pt_file_block_preserves_cache_control: the dead copy
  passes model and llm_provider explicitly and uses real base64 PDF content.
- test_translate_streaming_openai_chunk_to_anthropic_with_thinking: the dead copy
  covers thinking_delta; the survivor covers signature_delta.
- test_client_initialization and test_client_without_api_key: the dead copies
  assert the resource clients are wired with the right base URL and key; the
  survivors only construct the object.
- test_client_initialization_strips_trailing_slash: the dead copy constructs
  ModelsManagementClient directly rather than going through Client.

Verification: collecting the seven touched files gives 401 node IDs before and
411 after, the ten new names and nothing else, with nothing lost. All ten pass.
Running the touched files in full gives 299 passed, and test_optional_params.py
goes from 111 passed to 112.

Two further shadowed definitions were left alone rather than renamed: the dead
copies of test_prompt_caching and test_cost_calculator_with_base_model_with_router
have no assertions at all, one being a bare pass and the other a lone import, so
restoring them would add tests that cannot fail.
2026-08-12 11:15:54 -07:00

106 lines
3.2 KiB
Python

import os
import sys
import pytest
sys.path.insert(
0, os.path.abspath("../../..")
) # Adds the parent directory to the system path
from litellm.proxy.client import ChatClient, Client, ModelsManagementClient
from litellm.proxy.client.http_client import HTTPClient
from litellm.proxy.client.keys import KeysManagementClient
@pytest.fixture
def base_url():
return "http://localhost:8000"
@pytest.fixture
def api_key():
return "test-api-key"
def test_client_initialization_wires_resource_clients(base_url, api_key):
"""Test that the Client is properly initialized with all resource clients"""
client = Client(base_url=base_url, api_key=api_key)
# Check base properties
assert client._base_url == base_url
assert client._api_key == api_key
# Check resource clients
assert isinstance(client.models, ModelsManagementClient)
assert client.models._base_url == base_url
assert client.models._api_key == api_key
# Check chat client
assert isinstance(client.chat, ChatClient)
assert client.chat._base_url == base_url
assert client.chat._api_key == api_key
# Check keys client
assert isinstance(client.keys, KeysManagementClient)
assert client.keys._base_url == base_url
assert client.keys._api_key == api_key
# Check http client
assert isinstance(client.http, HTTPClient)
assert client.http._base_url == base_url
assert client.http._api_key == api_key
def test_client_initialization_strips_trailing_slash():
"""Test that the client properly strips trailing slashes from base_url during initialization"""
base_url = "http://localhost:8000/////"
client = Client(base_url=base_url)
assert client._base_url == "http://localhost:8000"
assert client.models._base_url == "http://localhost:8000"
assert client.chat._base_url == "http://localhost:8000"
assert client.keys._base_url == "http://localhost:8000"
assert client.http._base_url == "http://localhost:8000"
def test_client_without_api_key_propagates_none_to_resource_clients(base_url):
"""Test that the client works without an API key"""
client = Client(base_url=base_url)
assert client._api_key is None
assert client.models._api_key is None
assert client.chat._api_key is None
assert client.keys._api_key is None
assert client.http._api_key is None
def test_client_initialization():
"""Test that the client is initialized correctly."""
client = Client(
base_url="http://localhost:4000",
api_key="test-key",
timeout=60,
)
# Check that http client is initialized correctly
assert isinstance(client.http, HTTPClient)
assert client.http._base_url == "http://localhost:4000"
assert client.http._api_key == "test-key"
assert client.http._timeout == 60
def test_client_default_timeout():
"""Test that the client uses default timeout."""
client = Client(
base_url="http://localhost:4000",
api_key="test-key",
)
assert client.http._timeout == 30
def test_client_without_api_key():
"""Test that the client works without an API key."""
client = Client(base_url="http://localhost:4000")
assert client.http._api_key is None