tests: fix seven Windows-only failures, one POSIX assumption at a time - #120
Merged
9 commits merged intoSep 8, 2026
Merged
9 commits merged into
9 commits merged into
Conversation
…ed path test test_a_user_scoped_config_path_is_not_nested_under_the_repo set HOME to tmp_path itself and then asserted the config landed in tmp_path/.junie. Only posixpath.expanduser reads HOME. ntpath reads USERPROFILE, then HOMEDRIVE + HOMEPATH, and conftest's autouse isolated_home fixture already points all four at a `home` directory beneath tmp_path -- so on Windows the install correctly wrote its config under the fixture's home while the assertion looked one level up, in tmp_path itself. The fixture is the platform-independent answer and the test now takes it as a parameter instead of re-deriving home from an env var that three quarters of the supported platforms ignore. Signed-off-by: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… test test_install_never_destroys_a_config_it_cannot_parse seeded a config at tmp_path/.junie/config.json after setting HOME to tmp_path, then called install() and checked the user's settings survived. On Windows expanduser resolved ~ to the fixture's tmp_path/home, so install never saw the seeded file at all: it created a fresh config elsewhere, and every assertion here was reading a file nothing had touched. The BOM case passed vacuously and the unparseable cases raised JSONDecodeError from the test's own json.loads rather than ConfigUnreadableError from install. Home now comes from the isolated_home fixture, which sets every variable expanduser actually consults on both platform families. Signed-off-by: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… query test test_a_query_never_raises_on_an_unparseable_config wrote a corrupt config under a HOME it had set by hand, then asserted installed() returns False and uninstall() raises ConfigUnreadableError. On Windows the corrupt file was not on the path either call reads, so installed() returned False because nothing was there -- the right answer for the wrong reason -- and uninstall() found no file to fail on, which is why the test reported DID NOT RAISE. Home now comes from the isolated_home fixture. All three install tests that seeded a user-scoped config by hand are now consistent with it. Signed-off-by: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…all test kimi_code's CONFIG_PATH starts with ~/, so its config is user-scoped by design -- there is a test in this same file asserting exactly that. The install test still seeded the file at tmp_path/.kimi-code/config.toml after setting HOME by hand, which resolves nowhere on Windows. The result was the sharpest form of the failure: install() wrote a correct config under the fixture's home, the test read the untouched original it had seeded, and reported that guard.py was missing from a file install had never been asked to write. Home now comes from the isolated_home fixture. tmp_path stays as the repo root argument, which is a different thing and still belongs there. Signed-off-by: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…stall test test_reinstalling_replaces_our_block_rather_than_stacking_them read the config back from tmp_path/.kimi-code/config.toml after two installs. Both installs wrote to the home expanduser actually resolves, so on Windows the read raised FileNotFoundError before any assertion about stacked blocks ran. Home now comes from the isolated_home fixture, so the file the test reads is the file the installs wrote. `Path` is still used elsewhere in the module, so the import stays. Signed-off-by: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The generated pages carry em dashes. Both readers that compare a committed page against a freshly built one opened it with no encoding argument, so on a cp1252 host every em dash decoded to three characters that could never match. test_committed_pages_match_what_the_library_produces reported all twelve pages stale on Windows -- with no way to make it pass, because regenerating wrote the same bytes it had just failed to read back. Both readers now say encoding="utf-8": the test's, extracted into a _committed() helper that can carry the reason, and generate.py's --check path, which the pre-commit hook and the examples CI job both run and which had the identical latent bug. The writer says encoding="utf-8", newline="\n" for the same reason from the other side: a regeneration on Windows was writing CRLF into files the repo stores with LF, so every page showed as modified until git normalised it away. Same assumption, same fix, and it keeps a Windows regeneration byte-identical to a CI one. Signed-off-by: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
test_hook_is_executable read HOOK.stat().st_mode & 0o111. Windows has no POSIX execute bit, so that is 0 for every file in the tree -- including this one, which git records as 100755 and checks out executable on Linux and macOS. The test could not pass on Windows and told the truth about nothing there. It now reads the mode git records for the path. That is the mode a clone gets, which is what decides whether the hook runs, and it is the same answer on every platform. A hook that is not tracked at all now fails with its own message rather than an index error. Verified real rather than vacuous: git currently records 100755 for .githooks/pre-commit, and the assertion names the mode it found when it is anything else. Signed-off-by: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ssing test_a_query_never_raises_on_an_undecodable_toml_config carried the same hand-set HOME as the three install tests fixed earlier on this branch, but it did not fail on Windows. That is the worse outcome: installed() returned False because the utf-16 file was not on the path it reads, not because the TOML branch had decoded it safely. The test asserted its own setup. Not one of the seven reported failures. It is the same defect in the same file, found while fixing them, and it was reporting a pass for a branch it never entered. With home taken from the fixture, the file is on the path installed() reads: verified by writing a valid installed config to that path and watching installed() return True, then overwriting it with the utf-16 body and watching it return False without raising. Signed-off-by: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… behind each Signed-off-by: Claude <noreply@anthropic.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Merged
5 tasks
e94f29e
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.
Seven tests fail on a clean
mainon Windows and pass on the CI runners. Each rests on aPOSIX assumption that was never true off POSIX. None is skipped, deleted, or weakened; one
commit per failure, each named for the assumption it removes.
Full suite on Windows: 1534 passed, 4 skipped, 0 failed (was 7 failed).
The three assumptions
os.path.expanduserreadsHOME— five failures. It does on POSIX.ntpath.expanduserreads
USERPROFILE, thenHOMEDRIVE+HOMEPATH, and neverHOME.conftest.py'sautouse
isolated_homefixture already sets all four, and its docstring says exactly this.The five tests set
HOMEagain by hand and then asserted against a path derived from thatone variable, so on Windows they measured a directory nothing had written to.
The failure modes were worth reading rather than just fixing:
test_a_user_scoped_config_path_is_not_nested_under_the_repotest_install_never_destroys_a_config_it_cannot_parseJSONDecodeErrorfrom the test's ownjson.loads, notConfigUnreadableErrorfrom installtest_a_query_never_raises_on_an_unparseable_configinstalled()returnedFalsebecause nothing was there — right answer, wrong reason — anduninstall()had no file to fail on, hence DID NOT RAISEtest_install_appends_a_block_...untouchedguard.pymissingtest_reinstalling_replaces_our_block_...FileNotFoundErrorbefore any assertion about stacked blocks ranEach now takes
isolated_homeas a parameter.tmp_pathstays where it means the reporoot, which is a different argument and still belongs there.
The platform default text encoding is UTF-8 — one failure. The generated pages carry em
dashes; both readers that compare a committed page to a freshly built one used a bare
open(). Under cp1252 every em dash read back as three characters, so all twelve pagesreported stale — and could not be made to pass, because regenerating wrote the same bytes
it had just failed to read. Fixed in the test and in
examples/generate.py's--checkpath, which the pre-commit hook and the
examplesCI job both run and which carried theidentical latent bug. The writer now pins
encoding="utf-8", newline="\n"too: a Windowsregeneration was rewriting all thirteen pages with CRLF, so the same run that fixed one
page dirtied twelve others.
The filesystem carries a POSIX execute bit — one failure.
st_mode & 0o111is 0 forevery file on Windows, including one git records as
100755and checks out executable onLinux and macOS. The test now asserts on the mode git records for the path: that is what
travels with a clone, it decides whether the hook runs at all, and it is the same answer on
every platform. Confirmed non-vacuous — git currently records
100755, and the assertionnames the mode it found when it is anything else. An untracked hook now fails with its own
message rather than an index error.
One extra commit, not one of the seven
test_a_query_never_raises_on_an_undecodable_toml_configcarries the same hand-setHOMEas the three install tests, but it passed on Windows. That is the worse outcome:
installed()returnedFalsebecause the utf-16 file was not on the path it reads, notbecause the TOML branch had decoded it safely. The test asserted its own setup and never
entered the branch it is named for.
Fixed the same way, in its own commit, and verified non-vacuous by writing a valid
installed config to that path (
installed()→True), then overwriting it with the utf-16body (
installed()→False, no raise). Drop that commit if you would rather keep this PRto the seven.
Checks
ruff check .,ruff format --check .andtests/check_stdlib_only.pyclean. No blanketruff --fixwas run; no import reordering was needed.🤖 Generated with Claude Code