Skip to content

Commit 241942e

Browse files
committed
fix record_trampoline_hit when tmpdir changed working directory
1 parent 6453e6c commit 241942e

7 files changed

Lines changed: 35 additions & 2 deletions

File tree

e2e_projects/my_lib/src/my_lib/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,3 +234,7 @@ def divide(a: int, b: int):
234234
),
235235
)
236236
raise Exception(f'Cannot divide if {b=} cannot be 0!!!')
237+
238+
def write_into_file(path: str):
239+
with open(path, 'w') as file:
240+
file.write("Hello")

e2e_projects/my_lib/tests/test_my_lib.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,13 @@ def test_private_class_classmethod():
172172
def test_divide():
173173
with pytest.raises(Exception, match='.*cannot be 0!!!'):
174174
divide(1, 0)
175+
176+
def test_tmp_dir_switch(tmpdir):
177+
"""Verify that mutmut works with the tmpdir fixture"""
178+
# change to tmp directory
179+
with tmpdir.as_cwd():
180+
write_into_file("foo.txt")
181+
182+
with open("foo.txt", "r", encoding='utf-8') as file:
183+
data = file.read()
184+
assert "Hello" in data

src/mutmut/__main__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@
121121
def record_trampoline_hit(name: str, caller: str | None = None) -> None:
122122
assert not name.startswith("src."), "Failed trampoline hit. Module name starts with `src.`, which is invalid"
123123

124-
source_paths = [p.resolve(strict=True) for p in Config.get().source_paths]
124+
mutated_source_paths = Config.get().resolved_mutated_source_paths
125125

126126
if Config.get().max_stack_depth != -1:
127127
f = inspect.currentframe()
@@ -132,7 +132,7 @@ def record_trampoline_hit(name: str, caller: str | None = None) -> None:
132132
if "pytest" in filename or "hammett" in filename or "unittest" in filename:
133133
break
134134
file_path = Path(filename).resolve(strict=True)
135-
if any(path in file_path.parents for path in source_paths):
135+
if any(path in file_path.parents for path in mutated_source_paths):
136136
# only include stack frames of user-code; exclude mutmut and 3rd library stack frames
137137
c -= 1
138138

src/mutmut/configuration.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ def _load_config() -> Config:
103103
source_paths = [Path(path) for path in s("source_paths", [])]
104104
source_paths = source_paths or paths_to_mutate or [Path(path) for path in _guess_source_paths()]
105105

106+
# We resolve at startup, s.t. we are still in the current working directory (and no tests modified the directory)
107+
resolved_mutated_source_paths = [Path.cwd().resolve(strict=True) / "mutants" / p for p in source_paths]
108+
106109
tests_dir = s("tests_dir", [])
107110
if tests_dir:
108111
warnings.warn(
@@ -135,6 +138,7 @@ def _load_config() -> Config:
135138
debug=s("debug", False),
136139
mutate_only_covered_lines=s("mutate_only_covered_lines", False),
137140
source_paths=source_paths,
141+
resolved_mutated_source_paths=resolved_mutated_source_paths,
138142
pytest_add_cli_args=s("pytest_add_cli_args", []),
139143
pytest_add_cli_args_test_selection=pytest_add_cli_args_test_selection,
140144
timeout_multiplier=s("timeout_multiplier", 15.0),
@@ -164,6 +168,7 @@ class Config:
164168
max_stack_depth: int
165169
debug: bool
166170
source_paths: list[Path]
171+
resolved_mutated_source_paths: list[Path]
167172
pytest_add_cli_args: list[str]
168173
pytest_add_cli_args_test_selection: list[str]
169174
mutate_only_covered_lines: bool

tests/e2e/test_e2e_my_lib.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,16 @@ def test_my_lib_result_snapshot():
109109
"my_lib.xǁ_PrivateClassǁget_question__mutmut_3": 0,
110110
"my_lib.xǁ_PrivateClassǁget_answer__mutmut_1": 0,
111111
"my_lib.x_divide__mutmut_1": 1,
112+
"my_lib.x_write_into_file__mutmut_1": 1,
113+
"my_lib.x_write_into_file__mutmut_2": 1,
114+
"my_lib.x_write_into_file__mutmut_3": 1,
115+
"my_lib.x_write_into_file__mutmut_4": 1,
116+
"my_lib.x_write_into_file__mutmut_5": 1,
117+
"my_lib.x_write_into_file__mutmut_6": 1,
118+
"my_lib.x_write_into_file__mutmut_7": 1,
119+
"my_lib.x_write_into_file__mutmut_8": 0,
120+
"my_lib.x_write_into_file__mutmut_9": 1,
121+
"my_lib.x_write_into_file__mutmut_10": 1,
112122
}
113123
}
114124
)

tests/mutation/test_mutation.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,7 @@ def test_record_trampoline_hit_records_caller(monkeypatch):
12261226
cfg = Mock(spec=Config)
12271227
cfg.max_stack_depth = -1
12281228
cfg.source_paths = []
1229+
cfg.resolved_mutated_source_paths = []
12291230
cfg.track_dependencies = True
12301231
monkeypatch.setattr(Config, "get", lambda: cfg)
12311232

@@ -1244,6 +1245,7 @@ def test_record_trampoline_hit_skips_caller_when_disabled(monkeypatch):
12441245
cfg = Mock(spec=Config)
12451246
cfg.max_stack_depth = -1
12461247
cfg.source_paths = []
1248+
cfg.resolved_mutated_source_paths = []
12471249
cfg.track_dependencies = False
12481250
monkeypatch.setattr(Config, "get", lambda: cfg)
12491251

@@ -1318,6 +1320,7 @@ def _config_for_invalidation(**overrides):
13181320
max_stack_depth=-1,
13191321
debug=False,
13201322
source_paths=[pathlib.Path("src")],
1323+
resolved_mutated_source_paths=[(pathlib.Path("mutants") / "src").absolute()],
13211324
pytest_add_cli_args=[],
13221325
pytest_add_cli_args_test_selection=[],
13231326
mutate_only_covered_lines=False,

tests/test_configuration.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def _get_config(only_mutate: list[str], do_not_mutate: list[str]) -> Config:
6464
max_stack_depth=-1,
6565
debug=False,
6666
source_paths=[],
67+
resolved_mutated_source_paths=[],
6768
pytest_add_cli_args=[],
6869
pytest_add_cli_args_test_selection=[],
6970
mutate_only_covered_lines=False,

0 commit comments

Comments
 (0)