@@ -169,3 +169,162 @@ def test_show_wrong_path(private_dir):
169169 )
170170 result = pytester .runpytest ()
171171 result .stdout .fnmatch_lines ([str (p ) + ":*: AssertionError" , "*1 failed in *" ])
172+
173+
174+ class TestNodeidPrefixComputation :
175+ """Tests for nodeid prefix computation for paths outside rootdir."""
176+
177+ def test_path_in_site_packages_found (self , tmp_path : Path ) -> None :
178+ """Test _path_in_site_packages finds paths inside site-packages."""
179+ fake_site_packages = tmp_path / "site-packages"
180+ fake_site_packages .mkdir ()
181+ pkg_path = fake_site_packages / "mypackage" / "tests" / "test_foo.py"
182+ pkg_path .parent .mkdir (parents = True )
183+ pkg_path .touch ()
184+
185+ site_packages = frozenset ([fake_site_packages ])
186+ result = nodes ._path_in_site_packages (pkg_path , site_packages )
187+
188+ assert result is not None
189+ sp_dir , rel_path = result
190+ assert sp_dir == fake_site_packages
191+ assert rel_path == Path ("mypackage/tests/test_foo.py" )
192+
193+ def test_path_in_site_packages_not_found (self , tmp_path : Path ) -> None :
194+ """Test _path_in_site_packages returns None for paths outside site-packages."""
195+ fake_site_packages = tmp_path / "site-packages"
196+ fake_site_packages .mkdir ()
197+ other_path = tmp_path / "other" / "test_foo.py"
198+ other_path .parent .mkdir (parents = True )
199+ other_path .touch ()
200+
201+ site_packages = frozenset ([fake_site_packages ])
202+ result = nodes ._path_in_site_packages (other_path , site_packages )
203+
204+ assert result is None
205+
206+ def test_compute_nodeid_inside_rootpath (self , tmp_path : Path ) -> None :
207+ """Test nodeid computation for paths inside rootpath."""
208+ rootpath = tmp_path / "project"
209+ rootpath .mkdir ()
210+ test_file = rootpath / "tests" / "test_foo.py"
211+ test_file .parent .mkdir (parents = True )
212+ test_file .touch ()
213+
214+ result = nodes .compute_nodeid_prefix_for_path (
215+ path = test_file ,
216+ rootpath = rootpath ,
217+ invocation_dir = rootpath ,
218+ initial_paths = frozenset (),
219+ site_packages = frozenset (),
220+ )
221+
222+ assert result == "tests/test_foo.py"
223+
224+ def test_compute_nodeid_in_initial_paths (self , tmp_path : Path ) -> None :
225+ """Test nodeid computation for paths relative to initial_paths."""
226+ rootpath = tmp_path / "project"
227+ rootpath .mkdir ()
228+ tests_dir = tmp_path / "tests"
229+ tests_dir .mkdir ()
230+ test_file = tests_dir / "test_foo.py"
231+ test_file .touch ()
232+
233+ result = nodes .compute_nodeid_prefix_for_path (
234+ path = test_file ,
235+ rootpath = rootpath ,
236+ invocation_dir = rootpath ,
237+ initial_paths = frozenset ([tests_dir ]),
238+ site_packages = frozenset (),
239+ )
240+
241+ assert result == "test_foo.py"
242+
243+ def test_compute_nodeid_in_site_packages (self , tmp_path : Path ) -> None :
244+ """Test nodeid computation for paths in site-packages uses site:// prefix."""
245+ rootpath = tmp_path / "project"
246+ rootpath .mkdir ()
247+ fake_site_packages = tmp_path / "site-packages"
248+ fake_site_packages .mkdir ()
249+ pkg_test = fake_site_packages / "mypackage" / "tests" / "test_foo.py"
250+ pkg_test .parent .mkdir (parents = True )
251+ pkg_test .touch ()
252+
253+ result = nodes .compute_nodeid_prefix_for_path (
254+ path = pkg_test ,
255+ rootpath = rootpath ,
256+ invocation_dir = rootpath ,
257+ initial_paths = frozenset (),
258+ site_packages = frozenset ([fake_site_packages ]),
259+ )
260+
261+ assert result == "site://mypackage/tests/test_foo.py"
262+
263+ def test_compute_nodeid_nearby_relative (self , tmp_path : Path ) -> None :
264+ """Test nodeid computation for nearby paths uses relative path."""
265+ rootpath = tmp_path / "project"
266+ rootpath .mkdir ()
267+ sibling = tmp_path / "sibling" / "tests" / "test_foo.py"
268+ sibling .parent .mkdir (parents = True )
269+ sibling .touch ()
270+
271+ result = nodes .compute_nodeid_prefix_for_path (
272+ path = sibling ,
273+ rootpath = rootpath ,
274+ invocation_dir = rootpath ,
275+ initial_paths = frozenset (),
276+ site_packages = frozenset (),
277+ )
278+
279+ assert result == "../sibling/tests/test_foo.py"
280+
281+ def test_compute_nodeid_far_away_absolute (self , tmp_path : Path ) -> None :
282+ """Test nodeid computation for far-away paths uses absolute path."""
283+ rootpath = tmp_path / "deep" / "nested" / "project"
284+ rootpath .mkdir (parents = True )
285+ far_away = tmp_path / "other" / "location" / "tests" / "test_foo.py"
286+ far_away .parent .mkdir (parents = True )
287+ far_away .touch ()
288+
289+ result = nodes .compute_nodeid_prefix_for_path (
290+ path = far_away ,
291+ rootpath = rootpath ,
292+ invocation_dir = rootpath ,
293+ initial_paths = frozenset (),
294+ site_packages = frozenset (),
295+ )
296+
297+ # Should use absolute path since it's more than 2 levels up
298+ assert result == str (far_away )
299+
300+ def test_compute_nodeid_rootpath_itself (self , tmp_path : Path ) -> None :
301+ """Test nodeid computation for rootpath itself returns empty string."""
302+ rootpath = tmp_path / "project"
303+ rootpath .mkdir ()
304+
305+ result = nodes .compute_nodeid_prefix_for_path (
306+ path = rootpath ,
307+ rootpath = rootpath ,
308+ invocation_dir = rootpath ,
309+ initial_paths = frozenset (),
310+ site_packages = frozenset (),
311+ )
312+
313+ assert result == ""
314+
315+ def test_compute_nodeid_initial_path_itself (self , tmp_path : Path ) -> None :
316+ """Test nodeid computation for initial_path itself returns empty string."""
317+ rootpath = tmp_path / "project"
318+ rootpath .mkdir ()
319+ tests_dir = tmp_path / "tests"
320+ tests_dir .mkdir ()
321+
322+ result = nodes .compute_nodeid_prefix_for_path (
323+ path = tests_dir ,
324+ rootpath = rootpath ,
325+ invocation_dir = rootpath ,
326+ initial_paths = frozenset ([tests_dir ]),
327+ site_packages = frozenset (),
328+ )
329+
330+ assert result == ""
0 commit comments