diff options
author | Pedro Algarvio <pedro@algarvio.me> | 2020-08-27 17:52:16 +0100 |
---|---|---|
committer | Ran Benita <ran@unusedvar.com> | 2020-12-12 17:41:37 +0200 |
commit | b16c0912537bee06c83e202112f4b036e4fd66dc (patch) | |
tree | dddb8336bebd669a6009472722a7cf4442b65607 /testing | |
parent | 902739cfc3bbc3379e6ef99c8e250de35f52ecde (diff) | |
download | pytest-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.py | 158 |
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: |