headroom/tests/test_providers/test_deepseek.py
Abhay Singh b976378c3e
test(pricing): stop asserting DeepSeek pricing freshness on wall-clock time (#2428)
## Description

The shared `test` job is currently failing on every open PR because of a
wall-clock time-bomb in the DeepSeek pricing tests, not because of any
code change.


`tests/test_providers/test_deepseek.py::TestDeepSeekPricingModule::test_registry_staleness_and_source_url`
asserted:

```python
assert not registry.is_stale()
```

`PricingRegistry.is_stale()` returns `(date.today() - last_updated) >
timedelta(days=30)`. The DeepSeek registry ships `LAST_UPDATED =
date(2026, 6, 19)`, so this assertion holds only while the current date
stays within 30 days of that constant. Once it lapses, the test fails on
time alone, turning the `test` shard red for every unrelated PR in the
repo. It is failing right now (31 days past `LAST_UPDATED`).

This is not testing code behavior: it only checks that the machine's
clock is within 30 days of a hardcoded date. The sibling Anthropic and
OpenAI registries are 560 days old and make no such assertion, so
DeepSeek is the odd one out here rather than a deliberate freshness
gate.

## Fix

Drop the freshness assertion and keep the meaningful `source_url` check,
renaming the test to `test_registry_source_url` to match what it now
verifies.

The staleness mechanism stays fully and time-independently covered by
`tests/test_pricing.py::test_registry_staleness_and_warning`, which
builds registries with `date.today() - timedelta(days=30)` (asserts not
stale) and `date.today() - timedelta(days=31)` (asserts stale) plus the
warning text. So this removes a fragile environmental assertion without
reducing real coverage, and aligns DeepSeek with the Anthropic/OpenAI
registries.

## Type of Change

- [x] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- `tests/test_providers/test_deepseek.py`: remove the
wall-clock-dependent `assert not registry.is_stale()`, keep the
`source_url` assertion, rename the test to `test_registry_source_url`,
and add a comment explaining why freshness is not asserted here.

## Testing

- [x] Unit tests pass (`pytest`)
- [x] Linting passes (`ruff check .`)
- [x] Type checking passes (`mypy headroom`)
- [ ] New tests added for new functionality
- [ ] Manual testing performed

### Test Output

```text
$ uvx ruff@0.15.17 check tests/test_providers/test_deepseek.py
All checks passed!
```

## Real Behavior Proof

- Environment: Windows 11, Python 3.12, project venv (`uv sync --extra
proxy`), `uvx ruff@0.15.17`.
- Exact command / steps: with the current date at 31 days past
`LAST_UPDATED`, ran the registry's `is_stale()` and the fixed test body
against the real modules, plus the mechanism test from
`tests/test_pricing.py`.
- Observed result: `get_deepseek_registry().is_stale()` is `True` on the
current date (which is exactly what broke the old assertion); the fixed
`test_registry_source_url` body passes regardless of the date; and
`test_registry_staleness_and_warning` still passes, so the staleness
mechanism remains covered.
- Not tested: a live DeepSeek pricing fetch (out of scope; pricing
values are unchanged).

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] I have updated the CHANGELOG.md if applicable
2026-07-19 22:14:34 -07:00

230 lines
9.2 KiB
Python

"""Tests for DeepSeek model pricing and cost estimation."""
import pytest
from headroom.pricing.deepseek_prices import (
DEEPSEEK_PRICES,
get_deepseek_registry,
)
from headroom.pricing.registry import PricingRegistry
class TestDeepSeekPricingModule:
"""Tests for the DeepSeek pricing data module."""
def test_deepseek_pricing_contains_v4_models(self):
assert "deepseek-v4-flash" in DEEPSEEK_PRICES
assert "deepseek-v4-pro" in DEEPSEEK_PRICES
assert len(DEEPSEEK_PRICES) == 2
def test_deepseek_v4_flash_pricing(self):
pricing = DEEPSEEK_PRICES["deepseek-v4-flash"]
assert pricing.input_per_1m == 0.14
assert pricing.output_per_1m == 0.28
assert pricing.cached_input_per_1m == 0.0028
assert pricing.context_window == 1_000_000
assert pricing.provider == "deepseek"
assert pricing.notes is not None
def test_deepseek_v4_pro_pricing(self):
pricing = DEEPSEEK_PRICES["deepseek-v4-pro"]
assert pricing.input_per_1m == 0.435
assert pricing.output_per_1m == 0.87
assert pricing.cached_input_per_1m == 0.003625
assert pricing.context_window == 1_000_000
assert pricing.provider == "deepseek"
assert pricing.notes is not None
def test_get_deepseek_registry(self):
registry = get_deepseek_registry()
assert isinstance(registry, PricingRegistry)
assert registry.get_price("deepseek-v4-flash") is not None
assert registry.get_price("deepseek-v4-pro") is not None
assert registry.get_price("nonexistent") is None
def test_registry_source_url(self):
registry = get_deepseek_registry()
assert registry.source_url == "https://api-docs.deepseek.com/quick_start/pricing"
# Deliberately no `assert not registry.is_stale()` here: is_stale()
# compares the shipped LAST_UPDATED against date.today(), so asserting
# freshness makes this test fail on wall-clock time alone once the
# pricing date ages past STALENESS_THRESHOLD_DAYS (30) - which then
# breaks CI on every unrelated PR in the repo. The staleness mechanism
# is covered time-independently in tests/test_pricing.py, and the
# sibling Anthropic/OpenAI registries make no freshness assertion.
def test_deepseek_registry_estimate_cost(self):
registry = get_deepseek_registry()
cost = registry.estimate_cost("deepseek-v4-flash", input_tokens=1_000_000)
assert cost.cost_usd == 0.14
assert "input" in cost.breakdown
assert cost.pricing_date is not None
def test_deepseek_registry_estimate_cost_with_cached(self):
registry = get_deepseek_registry()
cost = registry.estimate_cost(
"deepseek-v4-flash",
input_tokens=1_000_000,
cached_input_tokens=1_000_000,
)
assert cost.cost_usd == 0.14 + 0.0028
class TestDeepSeekLiteLLMInjection:
"""Tests for DeepSeek V4 pricing injection into litellm."""
def test_deepseek_v4_models_in_litellm_model_cost(self):
from headroom.pricing.litellm_pricing import LITELLM_AVAILABLE, litellm
if not LITELLM_AVAILABLE:
pytest.skip("litellm not available")
assert "deepseek-v4-flash" in litellm.model_cost
assert "deepseek-v4-pro" in litellm.model_cost
def test_deepseek_v4_prefixed_models_in_litellm_model_cost(self):
from headroom.pricing.litellm_pricing import LITELLM_AVAILABLE, litellm
if not LITELLM_AVAILABLE:
pytest.skip("litellm not available")
assert "deepseek/deepseek-v4-flash" in litellm.model_cost
assert "deepseek/deepseek-v4-pro" in litellm.model_cost
def test_deepseek_v4_flash_litellm_pricing(self):
from headroom.pricing.litellm_pricing import LITELLM_AVAILABLE, litellm
if not LITELLM_AVAILABLE:
pytest.skip("litellm not available")
flash = litellm.model_cost["deepseek-v4-flash"]
assert flash["input_cost_per_token"] == 0.14 / 1_000_000
assert flash["output_cost_per_token"] == 0.28 / 1_000_000
assert flash["cache_read_input_token_cost"] == 0.0028 / 1_000_000
assert flash["litellm_provider"] == "deepseek"
def test_deepseek_v4_pro_litellm_pricing(self):
from headroom.pricing.litellm_pricing import LITELLM_AVAILABLE, litellm
if not LITELLM_AVAILABLE:
pytest.skip("litellm not available")
pro = litellm.model_cost["deepseek-v4-pro"]
assert pro["input_cost_per_token"] == 0.435 / 1_000_000
assert pro["output_cost_per_token"] == 0.87 / 1_000_000
assert pro["cache_read_input_token_cost"] == 0.003625 / 1_000_000
assert pro["litellm_provider"] == "deepseek"
def test_cost_per_token_resolves_deepseek_v4_flash(self):
from headroom.pricing.litellm_pricing import (
LITELLM_AVAILABLE,
litellm,
resolve_litellm_model,
)
if not LITELLM_AVAILABLE:
pytest.skip("litellm not available")
# resolve_litellm_model adds the deepseek/ prefix so that
# litellm.cost_per_token can determine the provider via
# get_llm_provider(). Bare model names without a provider prefix
# would fail with BadRequestError.
resolved = resolve_litellm_model("deepseek-v4-flash")
input_cost, output_cost = litellm.cost_per_token(
model=resolved,
prompt_tokens=1_000_000,
completion_tokens=1_000_000,
)
assert input_cost == pytest.approx(0.14, rel=0.01)
assert output_cost == pytest.approx(0.28, rel=0.01)
def test_resolve_litellm_model_prefixes_deepseek(self):
from headroom.pricing.litellm_pricing import resolve_litellm_model
resolved = resolve_litellm_model("deepseek-v4-flash")
assert resolved == "deepseek/deepseek-v4-flash"
def test_injection_does_not_overwrite_existing_upstream_entries(self):
"""If litellm upstream already has these, our injection is a no-op."""
from headroom.pricing.litellm_pricing import LITELLM_AVAILABLE, litellm
if not LITELLM_AVAILABLE:
pytest.skip("litellm not available")
# Force-inject with wrong value, then verify the injection guard
litellm.model_cost["deepseek-v4-flash"] = {"input_cost_per_token": 999}
# Reimport to trigger _inject_deepseek_pricing — but it should NOT overwrite
import importlib
import headroom.pricing.litellm_pricing as lp
importlib.reload(lp)
assert litellm.model_cost["deepseek-v4-flash"]["input_cost_per_token"] == 999
# Reset to correct value
litellm.model_cost["deepseek-v4-flash"] = {
"input_cost_per_token": 0.14 / 1_000_000,
"output_cost_per_token": 0.28 / 1_000_000,
"cache_read_input_token_cost": 0.0028 / 1_000_000,
"litellm_provider": "deepseek",
"max_tokens": 384_000,
"max_input_tokens": 1_000_000,
}
class TestDeepSeekAnthropicProviderFallback:
"""Tests that Anthropic provider's _get_pricing handles DeepSeek models."""
def test_deepseek_v4_flash_fallback(self):
from headroom.providers.anthropic import AnthropicProvider
provider = AnthropicProvider()
pricing = provider._get_pricing("deepseek-v4-flash")
assert pricing is not None
assert pricing["input"] == 0.14
assert pricing["output"] == 0.28
assert pricing["cached_input"] == 0.0028
def test_deepseek_v4_pro_fallback(self):
from headroom.providers.anthropic import AnthropicProvider
provider = AnthropicProvider()
pricing = provider._get_pricing("deepseek-v4-pro")
assert pricing is not None
assert pricing["input"] == 0.435
assert pricing["output"] == 0.87
assert pricing["cached_input"] == 0.003625
def test_deepseek_unknown_model_returns_none(self):
from headroom.providers.anthropic import AnthropicProvider
provider = AnthropicProvider()
pricing = provider._get_pricing("deepseek-unknown-model")
assert pricing is None
def test_deepseek_partial_match_v4_flash_alias(self):
from headroom.providers.anthropic import AnthropicProvider
provider = AnthropicProvider()
# Should match via partial match (flash in v4-flash)
pricing = provider._get_pricing("deepseek-v4-flash-v1")
assert pricing is not None
def test_estimate_cost_deepseek_v4_flash(self):
from headroom.providers.anthropic import AnthropicProvider
provider = AnthropicProvider()
cost = provider.estimate_cost(
input_tokens=1_000_000,
output_tokens=0,
model="deepseek-v4-flash",
)
assert cost is not None
assert cost == 0.14
def test_estimate_cost_deepseek_v4_flash_with_cache(self):
from headroom.providers.anthropic import AnthropicProvider
provider = AnthropicProvider()
cost = provider.estimate_cost(
input_tokens=1_000_000,
output_tokens=0,
model="deepseek-v4-flash",
cached_tokens=1_000_000,
)
assert cost is not None
# All 1M input tokens are cached, so cost = cached_input only
assert cost == 0.0028