fix: make the test-profile generator hermetic and re-runnable

test_profile_init_integration failed on any machine with a generated test
profile already present. Two causes, both real bugs rather than test noise:

- scripts/generate_test_profile.py mutated constants.APP_DIR at import time
  to append "tests". The value was captured when constants was first
  imported -- long before a test can monkeypatch Path.home -- so the script
  read the developer's real ~/.seedpass/tests, and a reload appended another
  "tests" segment. The mutation also leaked into every other importer of
  constants in the same process. The tests directory is now derived per call
  from constants.APP_DIR instead.

- initialize_profile assumed add_fingerprint returns None for an existing
  profile, which is what its docstring still promises; it actually raises
  ValueError. Re-running the generator against an existing profile therefore
  crashed. It now treats "already exists" as the ordinary case.

test_profile_init_integration also repoints constants.APP_DIR so it no
longer depends on the developer's home directory, and
test_generate_test_profile asserts against the derived tests directory
rather than the mutated global.

Verified hermetic: the test passes repeatedly and touches nothing under the
real ~/.seedpass. Full Python suite: 1178 passed, 16 skipped, 0 failed.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Fable 5 committed 2026-08-14 21:16:24 -04:00
1 parent c2d7306bb7
commit b885573315
3 files changed
+40 -14

No files matched your search

+9 -2
View File
@@ -27,7 +27,14 @@ def test_initialize_profile_creates_directories(monkeypatch):
seed, mgr, dir_path, fingerprint, cfg_mgr = gtp.initialize_profile("test")
assert cfg_mgr is not None
assert constants.APP_DIR.exists()
assert (constants.APP_DIR / "test_seed.txt").exists()
# Generated profiles live under APP_DIR/tests so they never mix with
# real ones. The script used to achieve this by mutating
# constants.APP_DIR at import time, which leaked into every other
# importer in the process; it now derives the path per call.
test_dir = gtp.test_app_dir()
assert test_dir == constants.APP_DIR / "tests"
assert test_dir.exists()
assert (test_dir / "test_seed.txt").exists()
assert dir_path.parent == test_dir
assert dir_path.exists()
assert dir_path.name == fingerprint
@@ -3,6 +3,7 @@ import importlib.util
from pathlib import Path
from tempfile import TemporaryDirectory
import constants
from seedpass.core.manager import PasswordManager, EncryptionMode
@@ -21,6 +22,11 @@ def test_initialize_profile_and_manager(monkeypatch):
with TemporaryDirectory() as tmpdir:
tmp_path = Path(tmpdir)
monkeypatch.setattr(Path, "home", lambda: tmp_path)
# constants.APP_DIR is computed from Path.home() when constants is
# first imported, which happens long before this monkeypatch. Without
# repointing it the script reads the developer's real ~/.seedpass and
# fails against whatever profile happens to live there.
monkeypatch.setattr(constants, "APP_DIR", tmp_path / ".seedpass")
gtp = load_script()