def test_cmdline_python_package_symlink( self, pytester: Pytester, monkeypatch ) -> None: """ --pyargs with packages with path containing symlink can have conftest.py in their package (#2985) """ monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False) dirname = "lib" d = pytester.mkdir(dirname) foo = d.joinpath("foo") foo.mkdir() foo.joinpath("__init__.py").touch() lib = foo.joinpath("bar") lib.mkdir() lib.joinpath("__init__.py").touch() lib.joinpath("test_bar.py").write_text( "def test_bar(): pass\ndef test_other(a_fixture):pass" ) lib.joinpath("conftest.py").write_text( "import pytest\[email protected]\ndef a_fixture():pass" ) d_local = pytester.mkdir("symlink_root") symlink_location = d_local / "lib" symlink_or_skip(d, symlink_location, target_is_directory=True) # The structure of the test directory is now: # . # ├── symlink_root # │ └── lib -> ../lib # └── lib # └── foo # ├── __init__.py # └── bar # ├── __init__.py # ├── conftest.py # └── test_bar.py # NOTE: the different/reversed ordering is intentional here. search_path = ["lib", os.path.join("symlink_root", "lib")] monkeypatch.setenv("PYTHONPATH", prepend_pythonpath(*search_path)) for p in search_path: monkeypatch.syspath_prepend(p) # module picked up in symlink-ed directory: # It picks up symlink_root/lib/foo/bar (symlink) via sys.path. result = pytester.runpytest("--pyargs", "-v", "foo.bar") pytester.chdir() assert result.ret == 0 result.stdout.fnmatch_lines( [ "symlink_root/lib/foo/bar/test_bar.py::test_bar PASSED*", "symlink_root/lib/foo/bar/test_bar.py::test_other PASSED*", "*2 passed*", ] )
def invocation_path(self, pytester: Pytester) -> Path: pytester.syspathinsert(pytester.path / "src") pytester.chdir() pkg = pytester.path.joinpath("src/pkg") pkg.mkdir(parents=True) pkg.joinpath("__init__.py").touch() pkg.joinpath("test.py").touch() return pytester.path
def test_cmdline_python_namespace_package( self, pytester: Pytester, monkeypatch ) -> None: """Test --pyargs option with namespace packages (#1567). Ref: https://packaging.python.org/guides/packaging-namespace-packages/ """ monkeypatch.delenv("PYTHONDONTWRITEBYTECODE", raising=False) search_path = [] for dirname in "hello", "world": d = pytester.mkdir(dirname) search_path.append(d) ns = d.joinpath("ns_pkg") ns.mkdir() ns.joinpath("__init__.py").write_text( "__import__('pkg_resources').declare_namespace(__name__)" ) lib = ns.joinpath(dirname) lib.mkdir() lib.joinpath("__init__.py").touch() lib.joinpath(f"test_{dirname}.py").write_text( f"def test_{dirname}(): pass\ndef test_other():pass" ) # The structure of the test directory is now: # . # ├── hello # │ └── ns_pkg # │ ├── __init__.py # │ └── hello # │ ├── __init__.py # │ └── test_hello.py # └── world # └── ns_pkg # ├── __init__.py # └── world # ├── __init__.py # └── test_world.py # NOTE: the different/reversed ordering is intentional here. monkeypatch.setenv("PYTHONPATH", prepend_pythonpath(*search_path)) for p in search_path: monkeypatch.syspath_prepend(p) # mixed module and filenames: monkeypatch.chdir("world") result = pytester.runpytest("--pyargs", "-v", "ns_pkg.hello", "ns_pkg/world") assert result.ret == 0 result.stdout.fnmatch_lines( [ "test_hello.py::test_hello*PASSED*", "test_hello.py::test_other*PASSED*", "ns_pkg/world/test_world.py::test_world*PASSED*", "ns_pkg/world/test_world.py::test_other*PASSED*", "*4 passed in*", ] ) # specify tests within a module pytester.chdir() result = pytester.runpytest( "--pyargs", "-v", "ns_pkg.world.test_world::test_other" ) assert result.ret == 0 result.stdout.fnmatch_lines( ["*test_world.py::test_other*PASSED*", "*1 passed*"] )