fix: prevent tests from touching real Steam files

Tests for pick_next_game were calling uninstall_other_games and
state.save against real filesystem paths, deleting installed games
and overwriting the user's state.json whenever tests or pre-commit
ran.

- Add conftest.py safety net that redirects STEAMAPPS_PATH,
  CONFIG_DIR, STATE_FILE, SNAPSHOT_FILE, CONFIG_FILE, and
  HOSTS_FILE to tmp_path in all steam_backlog_enforcer tests
- Add missing uninstall_other_games mock to 4 tests in
  test_scanning.py (test_picks_shortest, test_skips_finished,
  test_unknown_hours, test_picks_game_no_hours)
This commit is contained in:
Krzysztof kuhy Rudnicki 2026-03-25 21:15:40 +01:00
parent 16c6b207e6
commit 833c5755e8
2 changed files with 86 additions and 0 deletions

View File

@ -0,0 +1,70 @@
"""Safety conftest: prevent tests from touching real Steam/config files.
Redirects all filesystem paths used by the steam_backlog_enforcer package
to temporary directories. This stops tests from accidentally:
- Deleting real game files via uninstall_other_games / uninstall_game
- Overwriting ~/.config/steam_backlog_enforcer/state.json (losing the
user's current assignment)
- Reading real appmanifest files from ~/.local/share/Steam/steamapps
- Modifying /etc/hosts via the store blocker
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from unittest.mock import patch
import pytest
if TYPE_CHECKING:
from collections.abc import Iterator
from pathlib import Path
@pytest.fixture(autouse=True)
def _isolate_filesystem(tmp_path: Path) -> Iterator[None]:
"""Redirect all real filesystem paths to a temporary directory.
Individual tests that also patch these paths will simply override
this fixture's patches for the duration of their own ``with`` block.
"""
fake_config = tmp_path / "config"
fake_config.mkdir()
fake_steamapps = tmp_path / "steamapps"
fake_steamapps.mkdir()
fake_hosts = tmp_path / "hosts"
with (
# Config / state / snapshot paths (used by State.save, Config.save, etc.)
patch(
"python_pkg.steam_backlog_enforcer.config.CONFIG_DIR",
fake_config,
),
patch(
"python_pkg.steam_backlog_enforcer.config.CONFIG_FILE",
fake_config / "config.json",
),
patch(
"python_pkg.steam_backlog_enforcer.config.STATE_FILE",
fake_config / "state.json",
),
patch(
"python_pkg.steam_backlog_enforcer.config.SNAPSHOT_FILE",
fake_config / "snapshot.json",
),
# Steam game manifests / install dirs
patch(
"python_pkg.steam_backlog_enforcer.game_install.STEAMAPPS_PATH",
fake_steamapps,
),
# /etc/hosts (store blocker)
patch(
"python_pkg.steam_backlog_enforcer.store_blocker.HOSTS_FILE",
fake_hosts,
),
patch(
"python_pkg.steam_backlog_enforcer.config.HOSTS_FILE",
fake_hosts,
),
):
yield

View File

@ -228,6 +228,10 @@ class TestPickNextGame:
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
return_value=True,
),
patch(
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
return_value=0,
),
):
pick_next_game([g1, g2], state, config)
assert state.current_app_id == 2
@ -255,6 +259,10 @@ class TestPickNextGame:
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
return_value=True,
),
patch(
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
return_value=0,
),
):
pick_next_game([g1, g2], state, config)
assert state.current_app_id == 2
@ -331,6 +339,10 @@ class TestPickNextGame:
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
return_value=True,
),
patch(
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
return_value=0,
),
):
pick_next_game([g1, g2], state, config)
assert state.current_app_id == 2
@ -350,6 +362,10 @@ class TestPickNextGame:
"python_pkg.steam_backlog_enforcer.scanning.is_game_installed",
return_value=True,
),
patch(
"python_pkg.steam_backlog_enforcer.scanning.uninstall_other_games",
return_value=0,
),
):
pick_next_game([g1], state, config)
assert state.current_app_id == 1