Skip to content

bug: uv run pytest is not repeatable and writes the developer's real ~/.codealmanac #71

Description

@Hotragn

What happened?

uv run pytest is not repeatable. It passes once, then fails on the next run, because tests register into the developer's real ~/.codealmanac registry:

tests/test_validate.py::test_cli_validate_returns_nonzero_for_issues
IntegrityError: UNIQUE constraint failed: repositories.name

Two separate causes, both of which let tests reach real user state:

  1. 45 tests never request isolated_home and pass no explicit database_path, so AppConfig() falls back to ~/.codealmanac. This affects every platform, macOS and Linux included.
  2. On Windows the fixture does not isolate even when requested. It patches $HOME, but ntpath.expanduser reads %USERPROFILE% and ignores $HOME, so all 390 call sites of the fixture run against the real home.

What did you expect?

What CONTRIBUTING.md already promises: "Tests that touch user state should use the isolated_home fixture so they write under a temp ~/.codealmanac/, not the real registry."

Reproduction

rm -rf ~/.codealmanac
uv run pytest tests/test_validate.py -q    # 7 passed
uv run pytest tests/test_validate.py -q    # 1 failed, 6 passed   <-- same command

On Windows, additionally:

rm -rf ~/.codealmanac
uv run pytest -q
ls ~/.codealmanac        # codealmanac.db  repos/   <-- real global state created

Environment

  • OS: Windows 11 (cause 1 is platform-independent; cause 2 is Windows-only)
  • Python version: 3.13
  • CodeAlmanac version: 0.4.7 / main at 0f15350
  • Install method: local checkout
  • Almanac root: almanac/

Logs or output

$ sqlite3 ~/.codealmanac/codealmanac.db 'select repository_id, name, root_path from repositories'
repo_86e5aa4de43ad419|repo|C:/Users/hotra/AppData/Local/Temp/pytest-of-hotra/
pytest-391/test_cli_validate_returns_nonz0/repo

A real registry row pointing at a deleted pytest temp directory, plus a real ~/.codealmanac/repos/<id>/index.db.

Extra context

Why the second run fails specifically: repositories.name is NOT NULL UNIQUE, and RepositoryStore.remember upserts ON CONFLICT(repository_id) only — nothing handles a name conflict. So a fresh temp path registered under the already-taken name "repo" raises.

CI does not catch this because every job starts from a fresh container, so there is never a second run.

The consequence is worse than a failing test: because "registry entries are never auto-dropped", the junk row persists, and --all queries silently skip unreachable paths, so it accumulates unnoticed. The only remedy is deleting ~/.codealmanac, which also destroys the developer's real registry.

I have a fix up in #64 — two commits, one per cause: patch %USERPROFILE% (and fail loudly if Path.home() misses the sandbox, so an insufficient patch set can never silently degrade again), and make the fixture autouse so no test can opt out by forgetting an argument. Suite totals are identical before and after the autouse change, so nothing depended on seeing the real home.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions