← ClaudeAtlas

clirunner-envlisted

Click's CliRunner.invoke `env=` only overrides keys the dict names; an absent key is not deleted. Pass `{key: None}` to delete one. Use when a CLI test asserts on an env var being absent.
MrBinnacle/skills · ★ 0 · AI & Automation · score 62
Install: claude install-skill MrBinnacle/skills
# Click CliRunner: `env=None` deletes; absence does NOT ## Problem You wrote a CLI test where the SUT (system under test) branches on whether an env var is set. The test invokes the CLI via `CliRunner.invoke(cli, args, env=clean_env_dict)`, where `clean_env_dict` omits the env var you want absent. The test passes locally. You ship it. Later it turns out the test was never exercising the "var absent" branch — it was running with the var present (inherited from your shell), and your assertion happened to also pass for the "var present" code path. In a live-API-call test, this can mean the test SILENTLY makes the network call you thought you were preventing. ## Root cause Click's `CliRunner.invoke(env=...)` is an OVERRIDE dict, not a REPLACEMENT environment. It iterates the dict and applies each key: - `env[key] = "value"` → sets `os.environ[key] = "value"` for the duration of the invocation, restoring afterward - `env[key] = None` → calls `del os.environ[key]` for the duration of the invocation, restoring afterward - key absent from `env` → `os.environ[key]` is left UNTOUCHED Originally verified against `click/testing.py:534` on Click 8.1.x; re-checked 2026-08-23 and 2026-08-24 against the current published [testing module source](https://github.com/pallets/click/blob/stable/src/click/testing.py). The durable evidence is the signature: `env: Mapping[str, str | None] | None` on `CliRunner`, `CliRunner.invoke` and `CliRunner.isolation`. A value type of `str | None` is the A