test(agent): make Claude Code credential tests hermetic on macOS with Keychain entries - #43344
Conversation
… Keychain entries Several tests in tests/agent/test_anthropic_adapter.py fail on any contributor Mac where Claude Code is logged in: TestResolveAnthropicToken::test_falls_back_to_claude_code_credentials TestResolveAnthropicToken::test_prefers_refreshable_claude_code_credentials_over_static_anthropic_token TestRunOauthSetupToken::test_returns_token_from_credential_files TestRunOauthSetupToken::test_returns_token_from_env_var TestRunOauthSetupToken::test_returns_none_when_no_creds_found Root cause: these tests fake ~/.claude/.credentials.json by monkeypatching agent.anthropic_adapter.Path.home to a tmp_path, but read_claude_code_credentials() consults the macOS Keychain FIRST via _read_claude_code_credentials_from_keychain(), which the tests did not mock. Real (possibly expired) Keychain credentials shadow the fake file, so resolution returns the wrong token or None and the assertions fail. The remaining tests in TestResolveAnthropicToken, TestResolveWithRefresh, and TestRunOauthSetupToken only pass by luck of the developer's local Keychain state. Fix: add the same autouse no_keychain fixture that TestReadClaudeCodeCredentials already uses (monkeypatch the keychain reader to return None) to TestResolveAnthropicToken, TestResolveWithRefresh, and TestRunOauthSetupToken. No production code changes. Verified on macOS 15 with Claude Code logged in: before 5 failed / 154 passed, after 159 passed.
|
Hi @bionicbutterfly13 - I independently ran into this exact bug today and arrived at the same fix (autouse I verified it on a real Mac with Claude Code installed: before the fix, 5-6 of 160 tests in Just wanted to add a second independent confirmation that this is a real bug and the fix is correct - might help this get unstuck. Closed my duplicate (#49796) in favor of this one. |
|
Thanks for tightening this macOS-specific test isolation. Current No problems found in the PR diff. GitHub reports the PR as mergeable, so this should be a mechanical salvage. Automated hermes-sweeper review. |
|
Thanks @bionicbutterfly13 — closing as resolved on main: PR #74517 landed a suite-wide autouse Keychain guard (_neutralize_macos_keychain_creds, from #35464 by @y0shua1ee) that covers your three per-class fixtures as a strict subset. You were the earliest PR targeting the anthropic-adapter Keychain class (June 10) — credited here. Verified post-merge: the adapter tests can no longer read a developer's real Keychain entries. |
What does this PR do?
Makes the Claude Code credential-resolution tests in
tests/agent/test_anthropic_adapter.pyhermetic on macOS machines that have real Claude Code Keychain credentials.Today, 5 tests fail out of the box on any contributor Mac where Claude Code is (or has been) logged in:
Root cause: these tests fake
~/.claude/.credentials.jsonby monkeypatchingagent.anthropic_adapter.Path.hometo atmp_path, butread_claude_code_credentials()(agent/anthropic_adapter.py) checks the macOS Keychain first via_read_claude_code_credentials_from_keychain()— which the tests never mocked. The developer's real (possibly expired) Keychain entry shadows the fake credentials file, so resolution returns the wrong token (orNoneafter a failed live refresh) and the assertions fail, e.g.AssertionError: assert None == 'cc-auto-token'.The remaining tests in
TestResolveAnthropicToken,TestResolveWithRefresh, andTestRunOauthSetupTokencurrently pass only by luck of the local Keychain state (token expiry, refreshability), so the whole group is covered, not just the 5 currently-red tests.Fix: reuse the exact pattern the file already established —
TestReadClaudeCodeCredentialshas an autouseno_keychainfixture that monkeypatches_read_claude_code_credentials_from_keychainto returnNone. This PR adds the same fixture to the three affected classes. No production code changes.The other test files that touch this code path were audited and are already hermetic: they mock
resolve_anthropic_token/read_claude_code_credentialsat the function level, andtests/agent/test_anthropic_keychain.pymockssubprocess.rundirectly.Related Issue
Fixes #
Type of Change
Changes Made
tests/agent/test_anthropic_adapter.py: add an autouseno_keychainfixture (monkeypatchagent.anthropic_adapter._read_claude_code_credentials_from_keychain→None) toTestResolveAnthropicToken,TestResolveWithRefresh, andTestRunOauthSetupToken, mirroring the existing fixture onTestReadClaudeCodeCredentials. 21 insertions, no production code touched.How to Test
Claude Code-credentialsentry), check outmainand runpytest tests/agent/test_anthropic_adapter.py -q→ 5 failures as listed above.pytest tests/agent/test_anthropic_adapter.py -q→ all 159 tests pass.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AScreenshots / Logs
Before (clean
upstream/main, macOS 15, Claude Code logged in):After (this branch, same machine):