test: unwind environment writes in tests/test_litellm with monkeypatch - #37806
Open
yuneng-berri wants to merge 3 commits into
Open
test: unwind environment writes in tests/test_litellm with monkeypatch#37806yuneng-berri wants to merge 3 commits into
yuneng-berri wants to merge 3 commits into
Conversation
`os.environ["X"] = v` inside a test leaks the value into every test that runs after it in the same worker, so ordering decides the result. 262 of those writes across 40 files now go through pytest's `monkeypatch` fixture, which restores the previous value at teardown. The rewrite skips any test that a mock.patch-family decorator wraps, any test with defaulted positional parameters, any test whose own name is called directly elsewhere, and rebinds nothing inside nested defs, because in each of those cases appending a fixture parameter changes what pytest or mock binds. Ratchets the TQ004 ceiling from 768 to 506.
Contributor
Greptile SummaryThis PR replaces direct test environment writes with pytest monkeypatch operations so mutations unwind automatically, and lowers the TQ004 quality budget accordingly.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; the previously reported environment-restoration issue is fixed because all five affected tests now let monkeypatch record and restore inherited values.
|
| Filename | Overview |
|---|---|
| tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_resend_email.py | Uses monkeypatch.delenv before testing missing-key behavior, allowing pytest teardown to restore an inherited RESEND_API_KEY. |
| tests/test_litellm/enterprise/enterprise_callbacks/send_emails/test_sendgrid_email.py | Replaces pop-and-manual-restore logic with monkeypatch.delenv, preserving inherited SENDGRID_API_KEY state. |
| tests/test_litellm/proxy/auth/test_login_utils.py | Deletes UI_PASSWORD through monkeypatch so the original worker environment is restored after the test. |
| tests/test_litellm/test_add_deployment_no_master_key.py | Uses monkeypatch-managed deletion for LITELLM_SALT_KEY, avoiding loss of inherited state. |
| tests/test_litellm/test_count_tokens_public_api.py | Uses monkeypatch-managed deletion for OPENAI_API_KEY, preserving its pre-test value at teardown. |
| test-quality-budget.json | Ratchets the TQ004 ceiling down by the same 262 violations removed by the test updates. |
Reviews (2): Last reviewed commit: "fix(test): delete the key through monkey..." | Re-trigger Greptile
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…irst Five tests popped a key straight out of `os.environ`, ran, then restored it with `monkeypatch.setenv`. By the time monkeypatch saw the name it was already gone, so it recorded "absent" as the value to go back to and deleted the key at teardown. On a worker that inherited a real `RESEND_API_KEY`, `SENDGRID_API_KEY`, `UI_PASSWORD`, `LITELLM_SALT_KEY` or `OPENAI_API_KEY`, every test after the first one ran without it. `monkeypatch.delenv(..., raising=False)` removes the key and restores whatever was there, so the try/finally the manual restore needed goes with it.
Collaborator
Author
|
Fixed: all five pop-then-restore sites now use monkeypatch.delenv, so the inherited value survives teardown. @greptileai |
…em fully Both files are also in #37815, which converts the module-global writes as well as the env writes and folds them into one fixture. Two PRs rewriting the same lines differently is a conflict nobody benefits from resolving, so this one drops back to staging on those two and keeps the other 39. TQ004 clears 200 here instead of 275; the rest moves with #37815.
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TLDR
Problem this solves:
os.environHow it solves it:
monkeypatch.setenv, which unwinds at teardownUser Flow
No end-user behavior changes and no test behavior changes. The same 1,732 tests
pass, and one fewer environment variable survives the session.
Relevant issues
Linear ticket
Pre-Submission checklist
Screenshots / Proof of Fix
Shared setup: a leak counter, run as a pytest plugin, so the two sides are
comparable rather than asserted.
Both sides run the same 38 files, in the same order, with the same command:
Before (ff02d5c)
The rule's count
python scripts/check_test_quality.py tests | grep -c ' TQ004 'What the session leaves behind
LITELLM_LICENSEwas already set on the machine, and a test overwrote it forevery test that ran after it.
APISERPENT_API_KEYwas invented by a test andleft behind
After (7219e7a)
The rule's count
python scripts/check_test_quality.py tests | grep -c ' TQ004 'What the session leaves behind
LITELLM_LOCAL_MODEL_COST_MAPas conftest-owned; it was not, it came fromthe two cost-calc files that now belong to test(cost-calc): stop 182 global writes leaking out of the cost-calc suites #37815
The ratchet
python scripts/test_quality_gate.py --updatepython scripts/test_quality_gate.py --base origin/litellm_internal_stagingType
✅ Test
Caveats (if any)
mock.patchfamily decorator wraps the test, so pytest may not injectdefcan shadow the name, so the inner one winsdelenv, so nothing is droppedFinal Attestation