Ray's Knowledge Base

A test that shells out to a real CLI with side effects can change the user's real config

PitfallVerified 27 Sep 2026Holds anywhere
Pitfall. The symptom, what causes it, and the fix that was run and seen to work.

Symptom#

After cargo test (or any test run), the developer's real tool configuration has changed: for example a plugin and a marketplace installed in their real Claude Code, pointing at a temporary folder that no longer exists.

Cause#

The code under test runs an external command with side effects (here claude plugin marketplace add and claude plugin install) through a program name that defaults to the real command unless an environment variable names a fake. Tests that forget the fake, often older tests written before the command was added, run the real command against the real $HOME.

Fix#

Make the program fail closed in test builds, so a forgotten fake fails instead of reaching the real tool:

pub fn external_program() -> String {
    if cfg!(test) {
        return "/nonexistent/program-in-unit-tests".into();
    }
    std::env::var("MYTOOL_PROGRAM").unwrap_or_else(|_| "program".into())
}

Do the same for every path taken from the environment (XDG_DATA_HOME, XDG_CACHE_HOME, HOME), and give integration tests their own HOME, XDG_*, working directory and a fake script on PATH. Clean up anything that leaked with the tool's own commands, not by editing its files.

Evidence#

In rkb (project rkb), a doctor unit test called the install plan without the fake and ran the real claude: it left rkb@rkb, a rkb marketplace and ~/.claude/plugins/cache/rkb/rkb/0.1.0-664efa454a8a in the real Claude Code. claude plugin uninstall rkb@rkb and claude plugin marketplace remove rkb removed them; after the cfg!(test) guard, repeated full test runs left the real config unchanged. Sharing the real cache folder also made a test fail now and then in parallel runs.