Skip to content

test: remove tests that mutation analysis proved assert nothing - #34475

Merged
yuneng-berri merged 3 commits into
litellm_internal_stagingfrom
litellm_/test-coverage-mutation-analysis-e42223
Jul 24, 2026
Merged

test: remove tests that mutation analysis proved assert nothing#34475
yuneng-berri merged 3 commits into
litellm_internal_stagingfrom
litellm_/test-coverage-mutation-analysis-e42223

Conversation

@yuneng-berri

@yuneng-berri yuneng-berri commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

This PR removes 30 test functions that a mutation testing sweep proved cannot fail when the code they exercise breaks. For each removed test, every source function it executes had mutants generated and scored, and the owning test file killed zero of them, meaning these tests pass unchanged against arbitrarily broken implementations of what they appear to cover

The sweep scored each mirror test file by mutating its source module (mutmut 3.5.0 in a Linux py3.12 container, with mutation restricted to lines the file actually covers) and running only that file against the mutants. A test was only removed when the verdict had full power: the pair's mutation run completed with no unchecked mutants, the test's covered functions had scored mutants, and none were killed. Four additional zero-kill tests in test_redis_cache.py were kept because git blame ties them to the regression fix in #31288; they need a rewrite rather than removal. A follow-up commit removes five more tests in llms/custom_httpx/test_http_handler.py, whose verdict reached full power only after the initial batch landed, once its mutation run completed with the schemata-incompatible ssl tests excluded from scoring

Relevant issues

Linear ticket

Pre-Submission checklist

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review (Greptile reviews automatically once the PR is opened; only comment @greptileai to re-request a review after pushing changes)

The first item is intentionally unchecked; this PR removes tests that provably assert nothing rather than adding new ones

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

Per-test evidence from the mutation sweep, captured at commit 9b0a424 (the tree the sweep scored). Each row says: the removed test executes N source functions that had scored mutants, those functions had M scored mutants total, and the entire test file killed 0 of them

Removed test Source functions it executes that had scored mutants Scored mutants across those functions Killed by the whole file
caching/test_redis_cache.py::test_async_lpop_pipeline_propagates_redis_exception 1 16 0
caching/test_redis_cache.py::test_async_lpop_pipeline_raises_on_per_command_error 1 16 0
caching/test_redis_cache.py::test_async_lpop_pipeline_redis_lt7_regroups_flat_results 1 16 0
caching/test_redis_cache.py::test_async_lpop_pipeline_single_round_trip 1 16 0
caching/test_redis_cache.py::test_async_lpop_with_float_redis_version 1 16 0
caching/test_redis_cache.py::test_async_rpush_pipeline_executes_all_operations 1 16 0
caching/test_redis_cache.py::test_async_rpush_pipeline_raises_on_per_command_error 1 16 0
caching/test_redis_cache.py::test_async_rpush_pipeline_raises_on_redis_error 1 16 0
caching/test_redis_cache.py::test_redis_cache_async_batch_get_cache 1 16 0
caching/test_redis_cache.py::test_redis_cache_async_increment 1 16 0
caching/test_redis_cache.py::test_redis_cache_async_increment_default_does_not_bump_existing_ttl 1 16 0
caching/test_redis_cache.py::test_redis_cache_async_increment_refresh_ttl_true_bumps_existing_ttl 1 16 0
llms/pass_through/guardrail_translation/test_handler.py::test_bedrock_converse_stream_is_supported 1 4 0
llms/pass_through/guardrail_translation/test_handler.py::test_bedrock_invoke_stream_is_not_supported 1 4 0
llms/pass_through/guardrail_translation/test_handler.py::test_bedrock_provider_delegates_output_to_bedrock_handler 1 4 0
llms/pass_through/guardrail_translation/test_handler.py::test_bedrock_provider_delegates_to_bedrock_handler 1 4 0
llms/pass_through/guardrail_translation/test_handler.py::test_bedrock_provider_dispatches_to_handler 1 4 0
llms/pass_through/guardrail_translation/test_handler.py::test_missing_provider_is_not_supported 1 4 0
llms/pass_through/guardrail_translation/test_handler.py::test_missing_provider_returns_original_bytes 1 4 0
llms/pass_through/guardrail_translation/test_handler.py::test_missing_provider_skips 1 4 0
llms/pass_through/guardrail_translation/test_handler.py::test_unknown_provider_is_not_supported 1 4 0
llms/pass_through/guardrail_translation/test_handler.py::test_unknown_provider_returns_original_bytes 1 4 0
llms/pass_through/guardrail_translation/test_handler.py::test_unknown_provider_skips_apply_guardrail 1 4 0
llms/pass_through/guardrail_translation/test_handler.py::test_unknown_provider_skips_output 1 4 0
proxy/test_proxy_server.py::test_embedding_input_array_of_tokens 1 22 0
llms/custom_httpx/test_http_handler.py::test_aiohttp_transport_trust_env_setting 1 3 0
llms/custom_httpx/test_http_handler.py::test_create_aiohttp_transport_with_closed_session 1 3 0
llms/custom_httpx/test_http_handler.py::test_create_aiohttp_transport_without_shared_session 1 3 0
llms/custom_httpx/test_http_handler.py::test_session_validation 1 3 0
llms/custom_httpx/test_http_handler.py::test_ssl_context_transport 1 3 0

The three edited files pass standalone before the change at 9b0a424 (each pair's mutation run requires a green baseline before scoring) and after the change at HEAD:

commit 4db6955451
pytest tests/test_litellm/caching/test_redis_cache.py tests/test_litellm/llms/pass_through/guardrail_translation/test_handler.py tests/test_litellm/proxy/test_proxy_server.py
317 passed, 14 warnings in 22.84s

Type

✅ Test

Changes

tests/test_litellm/caching/test_redis_cache.py loses 12 zero-kill tests around async_increment, batch_get_cache, and the rpush and lpop pipelines; their assertions only echoed their own mocks. The four namespace regression tests from #31288 stay

tests/test_litellm/llms/pass_through/guardrail_translation/test_handler.py loses its four handler-behavior classes, whose tests asserted mock delegation rather than outcomes, plus the helper and imports only they used. The registry tests remain

tests/test_litellm/proxy/test_proxy_server.py loses test_embedding_input_array_of_tokens

Final Attestation

  • The tests check the right things, including the edge cases, and regressions in the respective real-world customer use-cases are not possible after this PR

25 test functions across three files pass unchanged when every function
they execute is mutated; the owning file killed zero of their scored
mutants. Four zero-kill tests tied to the fix in #31288 are kept for
rewrite instead of removal.
…itellm_/test-coverage-mutation-analysis-e42223
@greptile-apps

greptile-apps Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Removes mutation-ineffective tests from four test modules.

  • Deletes Redis cache tests whose mocked behavior killed no source mutants.
  • Removes ineffective HTTP transport, guardrail translation, and embedding-input tests.
  • Retains registry and targeted Redis regression tests.

Confidence Score: 5/5

The PR appears safe to merge with no new blocking failures eligible for this follow-up review.

No blocking failure remains within the scope of the previous review thread.

Important Files Changed

Filename Overview
tests/test_litellm/caching/test_redis_cache.py Removes twelve mutation-ineffective tests around Redis increments, batch reads, and pipelines while retaining targeted regression tests.
tests/test_litellm/llms/custom_httpx/test_http_handler.py Removes five mutation-ineffective aiohttp transport and session-validation tests.
tests/test_litellm/llms/pass_through/guardrail_translation/test_handler.py Removes mocked handler-behavior tests and their unused imports and helper, leaving registry coverage.
tests/test_litellm/proxy/test_proxy_server.py Removes the mutation-ineffective embedding token-array proxy test.

Reviews (2): Last reviewed commit: "test: remove five more zero-kill tests f..." | Re-trigger Greptile

@@ -22,78 +22,6 @@ def redis_no_ping():
yield

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Redis regression coverage removed

These deletions leave async_increment TTL semantics, Redis-version parsing, batch decoding, pipeline regrouping, and per-command error propagation without direct coverage. Please replace the ineffective tests with mutation-effective assertions so regressions affecting spend counters, rate-limit windows, and Redis update buffering remain detectable.

Rule Used: What: Flag any modifications to existing tests and... (source)

Knowledge Base Used: Response Caching

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@codecov

codecov Bot commented Jul 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@yuneng-berri

Copy link
Copy Markdown
Contributor Author

The removed tests executed those paths but could not detect breakage in them: across the functions each test touches, the mutation run scored their covered sets and the whole file killed zero of the mutants, so the coverage being removed was line execution without behavioral assertion. The evidence table in the description lists this per test

Replacing them is deliberately sequenced as a follow-up rather than bundled here, so the new tests get written against the recorded surviving mutants (the concrete uncaught behavior changes) instead of re-mocking the same seams, and so this PR stays removal-only with its evidence reviewable in isolation. The four namespace regression tests tied to #31288 were kept for exactly the concern you raise

@greptileai

@greptile-apps

greptile-apps Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

The mutation evidence is rigorous and the sequencing argument is sound. Writing replacement tests against the recorded surviving mutants rather than re-mocking the same seams is exactly the right approach — it forces the new tests to assert real behavioral outcomes instead of reproducing the same structural flaw.

The four kept namespace regression tests confirm you're applying the distinction correctly: retained because they cover known regressions, removed because zero-kill on scored mutants is an objective verdict regardless of line coverage.

This is acceptable as a removal-only PR given the evidence provided. The key ask is that the follow-up actually lands — the surviving mutant list should drive the new test authorship directly.

The http_handler pair only received its full mutation verdict after the
first removal batch landed; these five tests pass unchanged when every
function they execute is mutated and the owning file killed none of
their scored mutants. The ssl tests excluded from mutation scoring are
untouched.
@yuneng-berri

Copy link
Copy Markdown
Contributor Author

@greptile review again

@yuneng-berri
yuneng-berri merged commit 7047a37 into litellm_internal_staging Jul 24, 2026
76 of 77 checks passed
@yuneng-berri
yuneng-berri deleted the litellm_/test-coverage-mutation-analysis-e42223 branch July 24, 2026 23:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants