def test_syspath_prepend_with_namespace_packages( pytester: Pytester, monkeypatch: MonkeyPatch) -> None: for dirname in "hello", "world": d = pytester.mkdir(dirname) 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").write_text("def check(): return %r" % dirname) monkeypatch.syspath_prepend("hello") import ns_pkg.hello assert ns_pkg.hello.check() == "hello" with pytest.raises(ImportError): import ns_pkg.world # Prepending should call fixup_namespace_packages. monkeypatch.syspath_prepend("world") import ns_pkg.world assert ns_pkg.world.check() == "world" # Should invalidate caches via importlib.invalidate_caches. modules_tmpdir = pytester.mkdir("modules_tmpdir") monkeypatch.syspath_prepend(str(modules_tmpdir)) modules_tmpdir.joinpath("main_app.py").write_text("app = True") from main_app import app # noqa: F401
def test_conftest_symlink_files(pytester: Pytester) -> None: """Symlinked conftest.py are found when pytest is executed in a directory with symlinked files.""" real = pytester.mkdir("real") source = { "app/test_foo.py": "def test1(fixture): pass", "app/__init__.py": "", "app/conftest.py": textwrap.dedent( """ import pytest print("conftest_loaded") @pytest.fixture def fixture(): print("fixture_used") """ ), } pytester.makepyfile(**{"real/%s" % k: v for k, v in source.items()}) # Create a build directory that contains symlinks to actual files # but doesn't symlink actual directories. build = pytester.mkdir("build") build.joinpath("app").mkdir() for f in source: symlink_or_skip(real.joinpath(f), build.joinpath(f)) os.chdir(build) result = pytester.runpytest("-vs", "app/test_foo.py") result.stdout.fnmatch_lines(["*conftest_loaded*", "PASSED"]) assert result.ret == ExitCode.OK
def file_structure(pytester: Pytester) -> None: pytester.makepyfile(test_foo=""" from foo import foo def test_foo(): assert foo() == 1 """) pytester.makepyfile(test_bar=""" from bar import bar def test_bar(): assert bar() == 2 """) foo_py = pytester.mkdir("sub") / "foo.py" content = dedent(""" def foo(): return 1 """) foo_py.write_text(content, encoding="utf-8") bar_py = pytester.mkdir("sub2") / "bar.py" content = dedent(""" def bar(): return 2 """) bar_py.write_text(content, encoding="utf-8")
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 test_exclude(pytester: Pytester) -> None: hellodir = pytester.mkdir("hello") hellodir.joinpath("test_hello.py").write_text("x y syntaxerror") hello2dir = pytester.mkdir("hello2") hello2dir.joinpath("test_hello2.py").write_text("x y syntaxerror") pytester.makepyfile(test_ok="def test_pass(): pass") result = pytester.runpytest("--ignore=hello", "--ignore=hello2") assert result.ret == 0 result.stdout.fnmatch_lines(["*1 passed*"])
def test_early_skip(self, pytester: Pytester) -> None: pytester.mkdir("xyz") pytester.makeconftest(""" import pytest def pytest_collect_file(): pytest.skip("early") """) result = pytester.runpytest() assert result.ret == ExitCode.NO_TESTS_COLLECTED result.stdout.fnmatch_lines(["*1 skip*"])
def _setup_tree(self, pytester: Pytester) -> Dict[str, Path]: # for issue616 # example mostly taken from: # https://mail.python.org/pipermail/pytest-dev/2014-September/002617.html runner = pytester.mkdir("empty") package = pytester.mkdir("package") package.joinpath("conftest.py").write_text( textwrap.dedent("""\ import pytest @pytest.fixture def fxtr(): return "from-package" """)) package.joinpath("test_pkgroot.py").write_text( textwrap.dedent("""\ def test_pkgroot(fxtr): assert fxtr == "from-package" """)) swc = package.joinpath("swc") swc.mkdir() swc.joinpath("__init__.py").touch() swc.joinpath("conftest.py").write_text( textwrap.dedent("""\ import pytest @pytest.fixture def fxtr(): return "from-swc" """)) swc.joinpath("test_with_conftest.py").write_text( textwrap.dedent("""\ def test_with_conftest(fxtr): assert fxtr == "from-swc" """)) snc = package.joinpath("snc") snc.mkdir() snc.joinpath("__init__.py").touch() snc.joinpath("test_no_conftest.py").write_text( textwrap.dedent("""\ def test_no_conftest(fxtr): assert fxtr == "from-package" # No local conftest.py, so should # use value from parent dir's """)) print("created directory structure:") for x in pytester.path.rglob(""): print(" " + str(x.relative_to(pytester.path))) return {"runner": runner, "package": package, "swc": swc, "snc": snc}
def test_doubledash_considered(pytester: Pytester) -> None: conf = pytester.mkdir("--option") conf.joinpath("conftest.py").touch() conftest = PytestPluginManager() conftest_setinitial(conftest, [conf.name, conf.name]) values = conftest._getconftestmodules(conf, importmode="prepend") assert len(values) == 1
def test_conftestcutdir(pytester: Pytester) -> None: conf = pytester.makeconftest("") p = pytester.mkdir("x") conftest = PytestPluginManager() conftest_setinitial(conftest, [pytester.path], confcutdir=p) values = conftest._getconftestmodules(p, importmode="prepend", rootpath=pytester.path) assert len(values) == 0 values = conftest._getconftestmodules(conf.parent, importmode="prepend", rootpath=pytester.path) assert len(values) == 0 assert not conftest.has_plugin(str(conf)) # but we can still import a conftest directly conftest._importconftest(conf, importmode="prepend", rootpath=pytester.path) values = conftest._getconftestmodules(conf.parent, importmode="prepend", rootpath=pytester.path) assert values[0].__file__ is not None assert values[0].__file__.startswith(str(conf)) # and all sub paths get updated properly values = conftest._getconftestmodules(p, importmode="prepend", rootpath=pytester.path) assert len(values) == 1 assert values[0].__file__ is not None assert values[0].__file__.startswith(str(conf))
def test_import_prepend_append( self, pytester: Pytester, monkeypatch: MonkeyPatch ) -> None: root1 = pytester.mkdir("root1") root2 = pytester.mkdir("root2") root1.joinpath("x456.py").touch() root2.joinpath("x456.py").touch() p = root2.joinpath("test_x456.py") monkeypatch.syspath_prepend(str(root1)) p.write_text( textwrap.dedent( """\ import x456 def test(): assert x456.__file__.startswith({!r}) """.format( str(root2) ) ) ) with monkeypatch.context() as mp: mp.chdir(root2) reprec = pytester.inline_run("--import-mode=append") reprec.assertoutcome(passed=0, failed=1) reprec = pytester.inline_run() reprec.assertoutcome(passed=1)
def test_collect_symlink_dir(pytester: Pytester) -> None: """A symlinked directory is collected.""" dir = pytester.mkdir("dir") dir.joinpath("test_it.py").write_text("def test_it(): pass", "utf-8") pytester.path.joinpath("symlink_dir").symlink_to(dir) result = pytester.runpytest() result.assert_outcomes(passed=2)
def test_skipif_markeval_namespace_multiple(self, pytester: Pytester) -> None: """Keys defined by ``pytest_markeval_namespace()`` in nested plugins override top-level ones.""" root = pytester.mkdir("root") root.joinpath("__init__.py").touch() root.joinpath("conftest.py").write_text( textwrap.dedent("""\ import pytest def pytest_markeval_namespace(): return {"arg": "root"} """)) root.joinpath("test_root.py").write_text( textwrap.dedent("""\ import pytest @pytest.mark.skipif("arg == 'root'") def test_root(): assert False """)) foo = root.joinpath("foo") foo.mkdir() foo.joinpath("__init__.py").touch() foo.joinpath("conftest.py").write_text( textwrap.dedent("""\ import pytest def pytest_markeval_namespace(): return {"arg": "foo"} """)) foo.joinpath("test_foo.py").write_text( textwrap.dedent("""\ import pytest @pytest.mark.skipif("arg == 'foo'") def test_foo(): assert False """)) bar = root.joinpath("bar") bar.mkdir() bar.joinpath("__init__.py").touch() bar.joinpath("conftest.py").write_text( textwrap.dedent("""\ import pytest def pytest_markeval_namespace(): return {"arg": "bar"} """)) bar.joinpath("test_bar.py").write_text( textwrap.dedent("""\ import pytest @pytest.mark.skipif("arg == 'bar'") def test_bar(): assert False """)) reprec = pytester.inline_run("-vs", "--capture=no") reprec.assertoutcome(skipped=3)
def test_invalid_test_module_name(self, pytester: Pytester) -> None: a = pytester.mkdir("a") a.joinpath("test_one.part1.py").touch() result = pytester.runpytest() result.stdout.fnmatch_lines([ "ImportError while importing test module*test_one.part1*", "Hint: make sure your test modules/packages have valid Python names.", ])
def test_cwd_snapshot(pytester: Pytester) -> None: foo = pytester.mkdir("foo") bar = pytester.mkdir("bar") os.chdir(foo) snapshot = CwdSnapshot() os.chdir(bar) assert Path().absolute() == bar snapshot.restore() assert Path().absolute() == foo
def test_issue151_load_all_conftests(pytester: Pytester) -> None: names = "code proj src".split() for name in names: p = pytester.mkdir(name) p.joinpath("conftest.py").touch() pm = PytestPluginManager() conftest_setinitial(pm, names) assert len(set(pm.get_plugins()) - {pm}) == len(names)
def test_conftest_existing_junitxml(pytester: Pytester) -> None: x = pytester.mkdir("tests") x.joinpath("conftest.py").write_text( textwrap.dedent("""\ def pytest_addoption(parser): parser.addoption("--xyz", action="store_true") """)) pytester.makefile(ext=".xml", junit="") # Writes junit.xml result = pytester.runpytest("-h", "--junitxml", "junit.xml") result.stdout.fnmatch_lines(["*--xyz*"])
def test_issue151_load_all_conftests(pytester: Pytester) -> None: names = "code proj src".split() for name in names: p = pytester.mkdir(name) p.joinpath("conftest.py").touch() conftest = PytestPluginManager() conftest_setinitial(conftest, names) d = list(conftest._conftestpath2mod.values()) assert len(d) == len(names)
def test_conftest_confcutdir(pytester: Pytester) -> None: pytester.makeconftest("assert 0") x = pytester.mkdir("x") x.joinpath("conftest.py").write_text( textwrap.dedent("""\ def pytest_addoption(parser): parser.addoption("--xyz", action="store_true") """)) result = pytester.runpytest("-h", "--confcutdir=%s" % x, x) result.stdout.fnmatch_lines(["*--xyz*"]) result.stdout.no_fnmatch_line("*warning: could not load initial*")
def test_required_option_help(pytester: Pytester) -> None: pytester.makeconftest("assert 0") x = pytester.mkdir("x") x.joinpath("conftest.py").write_text( textwrap.dedent("""\ def pytest_addoption(parser): parser.addoption("--xyz", action="store_true", required=True) """)) result = pytester.runpytest("-h", x) result.stdout.no_fnmatch_line("*argument --xyz is required*") assert "general:" in result.stdout.str()
def test_namespace_import_doesnt_confuse_import_hook( self, pytester: Pytester) -> None: """Ref #383. Python 3.3's namespace package messed with our import hooks. Importing a module that didn't exist, even if the ImportError was gracefully handled, would make our test crash. """ pytester.mkdir("not_a_package") p = pytester.makepyfile(""" try: from not_a_package import doesnt_exist except ImportError: # We handle the import error gracefully here pass def test_whatever(): pass """) res = pytester.runpytest(p.name) assert res.ret == 0
def test_tmp_path_always_is_realpath(pytester: Pytester, monkeypatch) -> None: # for reasoning see: test_tmpdir_always_is_realpath test-case realtemp = pytester.mkdir("myrealtemp") linktemp = pytester.path.joinpath("symlinktemp") attempt_symlink_to(linktemp, str(realtemp)) monkeypatch.setenv("PYTEST_DEBUG_TEMPROOT", str(linktemp)) pytester.makepyfile(""" def test_1(tmp_path): assert tmp_path.resolve() == tmp_path """) reprec = pytester.inline_run() reprec.assertoutcome(passed=1)
def test_conftest_found_with_double_dash(pytester: Pytester) -> None: sub = pytester.mkdir("sub") sub.joinpath("conftest.py").write_text( textwrap.dedent("""\ def pytest_addoption(parser): parser.addoption("--hello-world", action="store_true") """)) p = sub.joinpath("test_hello.py") p.write_text("def test_hello(): pass") result = pytester.runpytest(str(p) + "::test_hello", "-h") result.stdout.fnmatch_lines(""" *--hello-world* """)
def test_setinitial_conftest_subdirs(pytester: Pytester, name: str) -> None: sub = pytester.mkdir(name) subconftest = sub.joinpath("conftest.py") subconftest.touch() conftest = PytestPluginManager() conftest_setinitial(conftest, [sub.parent], confcutdir=pytester.path) key = subconftest.resolve() if name not in ("whatever", ".dotdir"): assert key in conftest._conftestpath2mod assert len(conftest._conftestpath2mod) == 1 else: assert key not in conftest._conftestpath2mod assert len(conftest._conftestpath2mod) == 0
def test_setinitial_conftest_subdirs(pytester: Pytester, name: str) -> None: sub = pytester.mkdir(name) subconftest = sub.joinpath("conftest.py") subconftest.touch() pm = PytestPluginManager() conftest_setinitial(pm, [sub.parent], confcutdir=pytester.path) key = subconftest.resolve() if name not in ("whatever", ".dotdir"): assert pm.has_plugin(str(key)) assert len(set(pm.get_plugins()) - {pm}) == 1 else: assert not pm.has_plugin(str(key)) assert len(set(pm.get_plugins()) - {pm}) == 0
def test_issue109_sibling_conftests_not_loaded(self, pytester: Pytester) -> None: sub1 = pytester.mkdir("sub1") sub2 = pytester.mkdir("sub2") sub1.joinpath("conftest.py").write_text("assert 0") result = pytester.runpytest(sub2) assert result.ret == ExitCode.NO_TESTS_COLLECTED sub2.joinpath("__init__.py").touch() p = sub2.joinpath("test_hello.py") p.touch() result = pytester.runpytest(p) assert result.ret == ExitCode.NO_TESTS_COLLECTED result = pytester.runpytest(sub1) assert result.ret == ExitCode.USAGE_ERROR
def test_mktemp(pytester: Pytester, basename: str, is_ok: bool) -> None: mytemp = pytester.mkdir("mytemp") p = pytester.makepyfile(""" def test_abs_path(tmp_path_factory): tmp_path_factory.mktemp('{}', numbered=False) """.format(basename)) result = pytester.runpytest(p, "--basetemp=%s" % mytemp) if is_ok: assert result.ret == 0 assert mytemp.joinpath(basename).exists() else: assert result.ret == 1 result.stdout.fnmatch_lines("*ValueError*")
def test_conftest_import_order(pytester: Pytester, monkeypatch: MonkeyPatch) -> None: ct1 = pytester.makeconftest("") sub = pytester.mkdir("sub") ct2 = sub / "conftest.py" ct2.write_text("") def impct(p, importmode): return p conftest = PytestPluginManager() conftest._confcutdir = pytester.path monkeypatch.setattr(conftest, "_importconftest", impct) mods = cast(List[Path], conftest._getconftestmodules(sub, importmode="prepend")) expected = [ct1, ct2] assert mods == expected
def test_keep_duplicates(pytester: Pytester) -> None: """Test for issue https://github.com/pytest-dev/pytest/issues/1609 (#1609) Use --keep-duplicates to collect tests from duplicate directories. """ a = pytester.mkdir("a") fh = a.joinpath("test_a.py") fh.write_text( textwrap.dedent("""\ import pytest def test_real(): pass """)) result = pytester.runpytest("--keep-duplicates", str(a), str(a)) result.stdout.fnmatch_lines(["*collected 2 item*"])
def test_skip_duplicates_by_default(pytester: Pytester) -> None: """Test for issue https://github.com/pytest-dev/pytest/issues/1609 (#1609) Ignore duplicate directories. """ a = pytester.mkdir("a") fh = a.joinpath("test_a.py") fh.write_text( textwrap.dedent("""\ import pytest def test_real(): pass """)) result = pytester.runpytest(str(a), str(a)) result.stdout.fnmatch_lines(["*collected 1 item*"])
def test_tmpdir_always_is_realpath(pytester: Pytester) -> None: # the reason why tmpdir should be a realpath is that # when you cd to it and do "os.getcwd()" you will anyway # get the realpath. Using the symlinked path can thus # easily result in path-inequality # XXX if that proves to be a problem, consider using # os.environ["PWD"] realtemp = pytester.mkdir("myrealtemp") linktemp = pytester.path.joinpath("symlinktemp") attempt_symlink_to(linktemp, str(realtemp)) p = pytester.makepyfile(""" def test_1(tmpdir): import os assert os.path.realpath(str(tmpdir)) == str(tmpdir) """) result = pytester.runpytest("-s", p, "--basetemp=%s/bt" % linktemp) assert not result.ret