summaryrefslogtreecommitdiff
path: root/testing
diff options
context:
space:
mode:
authorPedro Algarvio <pedro@algarvio.me>2020-08-27 17:52:16 +0100
committerRan Benita <ran@unusedvar.com>2020-12-12 17:41:37 +0200
commitb16c0912537bee06c83e202112f4b036e4fd66dc (patch)
treedddb8336bebd669a6009472722a7cf4442b65607 /testing
parent902739cfc3bbc3379e6ef99c8e250de35f52ecde (diff)
downloadpytest-b16c0912537bee06c83e202112f4b036e4fd66dc.tar.gz
Add `pytest_markeval_namespace` hook.
Add a new hook , `pytest_markeval_namespace` which should return a dictionary. This dictionary will be used to augment the "global" variables available to evaluate skipif/xfail/xpass markers. Pseudo example ``conftest.py``: .. code-block:: python def pytest_markeval_namespace(): return {"color": "red"} ``test_func.py``: .. code-block:: python @pytest.mark.skipif("color == 'blue'", reason="Color is not red") def test_func(): assert False
Diffstat (limited to 'testing')
-rw-r--r--testing/test_skipping.py158
1 files changed, 158 insertions, 0 deletions
diff --git a/testing/test_skipping.py b/testing/test_skipping.py
index cfc0cdbca..fc66eb18e 100644
--- a/testing/test_skipping.py
+++ b/testing/test_skipping.py
@@ -1,4 +1,5 @@
import sys
+import textwrap
import pytest
from _pytest.pytester import Pytester
@@ -155,6 +156,136 @@ class TestEvaluation:
assert skipped
assert skipped.reason == "condition: config._hackxyz"
+ def test_skipif_markeval_namespace(self, pytester: Pytester) -> None:
+ pytester.makeconftest(
+ """
+ import pytest
+
+ def pytest_markeval_namespace():
+ return {"color": "green"}
+ """
+ )
+ p = pytester.makepyfile(
+ """
+ import pytest
+
+ @pytest.mark.skipif("color == 'green'")
+ def test_1():
+ assert True
+
+ @pytest.mark.skipif("color == 'red'")
+ def test_2():
+ assert True
+ """
+ )
+ res = pytester.runpytest(p)
+ assert res.ret == 0
+ res.stdout.fnmatch_lines(["*1 skipped*"])
+ res.stdout.fnmatch_lines(["*1 passed*"])
+
+ 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_skipif_markeval_namespace_ValueError(self, pytester: Pytester) -> None:
+ pytester.makeconftest(
+ """
+ import pytest
+
+ def pytest_markeval_namespace():
+ return True
+ """
+ )
+ p = pytester.makepyfile(
+ """
+ import pytest
+
+ @pytest.mark.skipif("color == 'green'")
+ def test_1():
+ assert True
+ """
+ )
+ res = pytester.runpytest(p)
+ assert res.ret == 1
+ res.stdout.fnmatch_lines(
+ [
+ "*ValueError: pytest_markeval_namespace() needs to return a dict, got True*"
+ ]
+ )
+
class TestXFail:
@pytest.mark.parametrize("strict", [True, False])
@@ -577,6 +708,33 @@ class TestXFail:
result.stdout.fnmatch_lines(["*1 failed*" if strict else "*1 xpassed*"])
assert result.ret == (1 if strict else 0)
+ def test_xfail_markeval_namespace(self, pytester: Pytester) -> None:
+ pytester.makeconftest(
+ """
+ import pytest
+
+ def pytest_markeval_namespace():
+ return {"color": "green"}
+ """
+ )
+ p = pytester.makepyfile(
+ """
+ import pytest
+
+ @pytest.mark.xfail("color == 'green'")
+ def test_1():
+ assert False
+
+ @pytest.mark.xfail("color == 'red'")
+ def test_2():
+ assert False
+ """
+ )
+ res = pytester.runpytest(p)
+ assert res.ret == 1
+ res.stdout.fnmatch_lines(["*1 failed*"])
+ res.stdout.fnmatch_lines(["*1 xfailed*"])
+
class TestXFailwithSetupTeardown:
def test_failing_setup_issue9(self, pytester: Pytester) -> None: