Skip to content

Commit 8ea37d3

Browse files
Add tests
1 parent d3fe9a5 commit 8ea37d3

3 files changed

Lines changed: 92 additions & 33 deletions

File tree

src/usethis/_integrations/project/imports.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ def _get_graph(pkg_name: str) -> grimp.ImportGraph:
123123
graph = grimp.build_graph(pkg_name, cache_dir=None)
124124
except ValueError as err:
125125
raise ImportGraphBuildFailedError(err) from None
126+
except ModuleNotFoundError as err:
127+
raise ImportGraphBuildFailedError(err) from None
126128
except grimp.exceptions.NotATopLevelModule:
127129
msg = f"Module {pkg_name} is not a top-level module, cannot build graph."
128130
raise ImportGraphBuildFailedError(msg) from None

src/usethis/_test.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
import os
44
import socket
5-
import sys
6-
from contextlib import contextmanager, suppress
5+
from contextlib import contextmanager
76
from pathlib import Path
87
from typing import TYPE_CHECKING
98

@@ -12,9 +11,7 @@
1211

1312

1413
@contextmanager
15-
def change_cwd(
16-
new_dir: Path, *, add_to_path: bool = False
17-
) -> Generator[None, None, None]:
14+
def change_cwd(new_dir: Path) -> Generator[None, None, None]:
1815
"""Change the working directory temporarily.
1916
2017
Arguments:
@@ -23,17 +20,11 @@ def change_cwd(
2320
"""
2421
old_dir = Path.cwd()
2522
os.chdir(new_dir)
26-
if add_to_path:
27-
sys.path.append(str(new_dir))
2823
try:
2924
yield
3025
finally:
3126
os.chdir(old_dir)
3227

33-
if add_to_path:
34-
with suppress(ValueError):
35-
sys.path.remove(str(new_dir))
36-
3728

3829
def is_offline() -> bool:
3930
try:

tests/usethis/_integrations/project/test_imports.py

Lines changed: 88 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717

1818
class TestGetLayeredArchitectures:
19-
def test_five(self, tmp_path: Path):
19+
def test_five(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
2020
# Arrange
2121
(tmp_path / "salut").mkdir()
2222
(tmp_path / "salut" / "__init__.py").touch()
@@ -38,8 +38,10 @@ def test_five(self, tmp_path: Path):
3838
""")
3939
(tmp_path / "salut" / "d" / "f.py").touch()
4040

41+
monkeypatch.syspath_prepend(str(tmp_path))
42+
4143
# Act
42-
with change_cwd(tmp_path, add_to_path=True):
44+
with change_cwd(tmp_path):
4345
arch_by_module = get_layered_architectures("salut")
4446

4547
# Assert
@@ -54,7 +56,7 @@ def test_five(self, tmp_path: Path):
5456

5557

5658
class TestGetModuleLayeredArchitecture:
57-
def test_three(self, tmp_path: Path):
59+
def test_three(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
5860
# Arrange
5961
(tmp_path / "salut").mkdir()
6062
(tmp_path / "salut" / "__init__.py").touch()
@@ -67,8 +69,10 @@ def test_three(self, tmp_path: Path):
6769
import salut.b
6870
""")
6971

72+
monkeypatch.syspath_prepend(str(tmp_path))
73+
7074
# Act
71-
with change_cwd(tmp_path, add_to_path=True):
75+
with change_cwd(tmp_path):
7276
graph = _get_graph("salut")
7377
arch = _get_module_layered_architecture("salut", graph=graph)
7478

@@ -77,15 +81,17 @@ def test_three(self, tmp_path: Path):
7781
assert arch.layers == [{"c"}, {"b"}, {"a"}]
7882
assert arch.excluded == set()
7983

80-
def test_independent(self, tmp_path: Path):
84+
def test_independent(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
8185
# Arrange
8286
(tmp_path / "salut").mkdir()
8387
(tmp_path / "salut" / "__init__.py").touch()
8488
(tmp_path / "salut" / "a.py").touch()
8589
(tmp_path / "salut" / "b.py").touch()
8690

91+
monkeypatch.syspath_prepend(str(tmp_path))
92+
8793
# Act
88-
with change_cwd(tmp_path, add_to_path=True):
94+
with change_cwd(tmp_path):
8995
graph = _get_graph("salut")
9096
arch = _get_module_layered_architecture("salut", graph=graph)
9197

@@ -94,7 +100,7 @@ def test_independent(self, tmp_path: Path):
94100
assert arch.layers == [{"a", "b"}]
95101
assert arch.excluded == set()
96102

97-
def test_cyclic(self, tmp_path: Path):
103+
def test_cyclic(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
98104
# Arrange
99105
(tmp_path / "salut").mkdir()
100106
(tmp_path / "salut" / "__init__.py").touch()
@@ -105,8 +111,10 @@ def test_cyclic(self, tmp_path: Path):
105111
import salut.a
106112
""")
107113

114+
monkeypatch.syspath_prepend(str(tmp_path))
115+
108116
# Act
109-
with change_cwd(tmp_path, add_to_path=True):
117+
with change_cwd(tmp_path):
110118
graph = _get_graph("salut")
111119
arch = _get_module_layered_architecture("salut", graph=graph)
112120

@@ -115,7 +123,7 @@ def test_cyclic(self, tmp_path: Path):
115123
assert arch.layers == []
116124
assert arch.excluded == {"a", "b"}
117125

118-
def test_bottom_heavy(self, tmp_path: Path):
126+
def test_bottom_heavy(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
119127
# For a given package structure, there are multiple possible layered
120128
# architectures it will comply with. We would prefer one which is "bottom heavy",
121129
# i.e. one or modules which depend on many independent modules, rather than
@@ -155,8 +163,10 @@ def test_bottom_heavy(self, tmp_path: Path):
155163
import salut.e
156164
""")
157165

166+
monkeypatch.syspath_prepend(str(tmp_path))
167+
158168
# Act
159-
with change_cwd(tmp_path, add_to_path=True):
169+
with change_cwd(tmp_path):
160170
graph = _get_graph("salut")
161171
arch = _get_module_layered_architecture("salut", graph=graph)
162172

@@ -167,7 +177,7 @@ def test_bottom_heavy(self, tmp_path: Path):
167177

168178

169179
class TestGetChildDependencies:
170-
def test_three(self, tmp_path: Path):
180+
def test_three(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
171181
# Arrange
172182
(tmp_path / "salut").mkdir()
173183
(tmp_path / "salut" / "__init__.py").touch()
@@ -180,8 +190,10 @@ def test_three(self, tmp_path: Path):
180190
import salut.b
181191
""")
182192

193+
monkeypatch.syspath_prepend(str(tmp_path))
194+
183195
# Act
184-
with change_cwd(tmp_path, add_to_path=True):
196+
with change_cwd(tmp_path):
185197
graph = _get_graph("salut")
186198
deps_by_module = _get_child_dependencies("salut", graph=graph)
187199

@@ -192,7 +204,7 @@ def test_three(self, tmp_path: Path):
192204
"c": {"a", "b"},
193205
}
194206

195-
def test_two(self, tmp_path: Path):
207+
def test_two(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
196208
# Arrange
197209
(tmp_path / "salut").mkdir()
198210
(tmp_path / "salut" / "__init__.py").touch()
@@ -201,8 +213,10 @@ def test_two(self, tmp_path: Path):
201213
import salut.a
202214
""")
203215

216+
monkeypatch.syspath_prepend(str(tmp_path))
217+
204218
# Act
205-
with change_cwd(tmp_path, add_to_path=True):
219+
with change_cwd(tmp_path):
206220
graph = _get_graph("salut")
207221
deps_by_module = _get_child_dependencies("salut", graph=graph)
208222

@@ -212,20 +226,22 @@ def test_two(self, tmp_path: Path):
212226
"b": {"a"},
213227
}
214228

215-
def test_none(self, tmp_path: Path):
229+
def test_none(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
216230
# Arrange
217231
(tmp_path / "salut").mkdir()
218232
(tmp_path / "salut" / "__init__.py").touch()
219233

234+
monkeypatch.syspath_prepend(str(tmp_path))
235+
220236
# Act
221-
with change_cwd(tmp_path, add_to_path=True):
237+
with change_cwd(tmp_path):
222238
graph = _get_graph("salut")
223239
deps_by_module = _get_child_dependencies("salut", graph=graph)
224240

225241
# Assert
226242
assert deps_by_module == {}
227243

228-
def test_submodule_file(self, tmp_path: Path):
244+
def test_submodule_file(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
229245
# Arrange
230246
(tmp_path / "salut").mkdir()
231247
(tmp_path / "salut" / "__init__.py").touch()
@@ -234,24 +250,28 @@ def test_submodule_file(self, tmp_path: Path):
234250
import salut.a
235251
""")
236252

253+
monkeypatch.syspath_prepend(str(tmp_path))
254+
237255
# Act
238-
with change_cwd(tmp_path, add_to_path=True):
256+
with change_cwd(tmp_path):
239257
graph = _get_graph("salut")
240258
deps_by_module = _get_child_dependencies("salut.a", graph=graph)
241259

242260
# Assert
243261
assert deps_by_module == {}
244262

245-
def test_submodule_dir(self, tmp_path: Path):
263+
def test_submodule_dir(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
246264
# Arrange
247265
(tmp_path / "salut").mkdir()
248266
(tmp_path / "salut" / "__init__.py").touch()
249267
(tmp_path / "salut" / "a").mkdir()
250268
(tmp_path / "salut" / "a" / "__init__.py").touch()
251269
(tmp_path / "salut" / "a" / "b.py").touch()
252270

271+
monkeypatch.syspath_prepend(str(tmp_path))
272+
253273
# Act
254-
with change_cwd(tmp_path, add_to_path=True):
274+
with change_cwd(tmp_path):
255275
graph = _get_graph("salut")
256276
deps_by_module = _get_child_dependencies("salut.a", graph=graph)
257277

@@ -302,13 +322,15 @@ def test_child_with_children(self):
302322

303323

304324
class TestGetGraph:
305-
def test_type(self, tmp_path: Path):
325+
def test_type(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
306326
# Arrange
307327
(tmp_path / "salut").mkdir()
308328
(tmp_path / "salut" / "__init__.py").touch()
309329

330+
monkeypatch.syspath_prepend(str(tmp_path))
331+
310332
# Act
311-
with change_cwd(tmp_path, add_to_path=True):
333+
with change_cwd(tmp_path):
312334
graph = _get_graph("salut")
313335

314336
# Assert
@@ -325,3 +347,47 @@ def test_does_not_exist(self, tmp_path: Path):
325347
# Act, Assert
326348
with pytest.raises(ImportGraphBuildFailedError):
327349
_get_graph("does_not_exist")
350+
351+
def test_not_top_level(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
352+
# Arrange
353+
(tmp_path / "salut").mkdir()
354+
(tmp_path / "salut" / "__init__.py").touch()
355+
(tmp_path / "salut" / "a.py").touch()
356+
357+
monkeypatch.syspath_prepend(str(tmp_path))
358+
359+
# Act, Assert
360+
with (
361+
change_cwd(tmp_path),
362+
pytest.raises(ImportGraphBuildFailedError),
363+
):
364+
_get_graph("salut.a")
365+
366+
def test_not_package(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
367+
# Arrange
368+
(tmp_path / "salut.py").touch()
369+
370+
monkeypatch.syspath_prepend(str(tmp_path))
371+
372+
# Act, Assert
373+
with (
374+
change_cwd(tmp_path),
375+
pytest.raises(ImportGraphBuildFailedError),
376+
):
377+
_get_graph("salut.a")
378+
379+
def test_exists_not_on_path(self, tmp_path: Path):
380+
# Arrange
381+
# N.B. we use the name 'different_name' since generating the graph in other
382+
# tests has the side-effect of importing the module, which persists between
383+
# tests.
384+
(tmp_path / "different_name.py").touch()
385+
386+
# Act, Assert
387+
with (
388+
change_cwd(tmp_path),
389+
pytest.raises(
390+
ImportGraphBuildFailedError, match="No module named 'different_name'"
391+
),
392+
):
393+
_get_graph("different_name.a")

0 commit comments

Comments
 (0)