Skip to content

Commit 7c602d4

Browse files
committed
Allow augmenting the variables available for skipif/xfail/xpass evaluation
1 parent 2fcf763 commit 7c602d4

File tree

3 files changed

+94
-0
lines changed

3 files changed

+94
-0
lines changed

src/_pytest/hookspec.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,16 @@ def pytest_warning_recorded(
808808
"""
809809

810810

811+
# -------------------------------------------------------------------------
812+
# Hooks for influencing skipping
813+
# -------------------------------------------------------------------------
814+
def pytest_markeval_namespace() -> Dict[str, Any]:
815+
"""Called when constructing the globals dictionary used for
816+
evaluating skipif contditions.
817+
Return a dictionary of additional globals to add.
818+
"""
819+
820+
811821
# -------------------------------------------------------------------------
812822
# error handling and internal debugging hooks
813823
# -------------------------------------------------------------------------

src/_pytest/skipping.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ def evaluate_condition(item: Item, mark: Mark, condition: object) -> Tuple[bool,
101101
"platform": platform,
102102
"config": item.config,
103103
}
104+
for dictionary in item.config.hook.pytest_markeval_namespace():
105+
if not isinstance(dictionary, dict) or not dictionary:
106+
continue
107+
globals_.update(dictionary)
104108
if hasattr(item, "obj"):
105109
globals_.update(item.obj.__globals__) # type: ignore[attr-defined]
106110
try:

testing/test_skipping.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,59 @@ def test_func(self):
153153
assert skipped
154154
assert skipped.reason == "condition: config._hackxyz"
155155

156+
def test_skipif_additional_globals(self, testdir):
157+
testdir.makeconftest(
158+
"""
159+
import pytest
160+
161+
def pytest_markeval_namespace():
162+
return {"color": "green"}
163+
"""
164+
)
165+
p = testdir.makepyfile(
166+
"""
167+
import pytest
168+
169+
@pytest.mark.skipif("color == 'green'")
170+
def test_1():
171+
assert True
172+
173+
@pytest.mark.skipif("color == 'red'")
174+
def test_2():
175+
assert True
176+
"""
177+
)
178+
res = testdir.runpytest(p)
179+
assert res.ret == 0
180+
res.stdout.fnmatch_lines(["*1 skipped*"])
181+
res.stdout.fnmatch_lines(["*1 passed*"])
182+
183+
def test_skipif_empty_additional_globals(self, testdir):
184+
testdir.makeconftest(
185+
"""
186+
import pytest
187+
188+
def pytest_markeval_namespace():
189+
return {}
190+
"""
191+
)
192+
p = testdir.makepyfile(
193+
"""
194+
import pytest
195+
196+
@pytest.mark.skipif(True, reason="because")
197+
def test_1():
198+
assert True
199+
200+
def test_2():
201+
assert True
202+
"""
203+
)
204+
res = testdir.runpytest(p)
205+
assert res.ret == 0
206+
res.stdout.fnmatch_lines(["*1 skipped*"])
207+
res.stdout.fnmatch_lines(["*1 passed*"])
208+
156209

157210
class TestXFail:
158211
@pytest.mark.parametrize("strict", [True, False])
@@ -569,6 +622,33 @@ def test_foo():
569622
result.stdout.fnmatch_lines(["*1 failed*" if strict else "*1 xpassed*"])
570623
assert result.ret == (1 if strict else 0)
571624

625+
def test_skipif_additional_globals(self, testdir):
626+
testdir.makeconftest(
627+
"""
628+
import pytest
629+
630+
def pytest_markeval_namespace():
631+
return {"color": "green"}
632+
"""
633+
)
634+
p = testdir.makepyfile(
635+
"""
636+
import pytest
637+
638+
@pytest.mark.xfail("color == 'green'")
639+
def test_1():
640+
assert False
641+
642+
@pytest.mark.xfail("color == 'red'")
643+
def test_2():
644+
assert False
645+
"""
646+
)
647+
res = testdir.runpytest(p)
648+
assert res.ret == 1
649+
res.stdout.fnmatch_lines(["*1 failed*"])
650+
res.stdout.fnmatch_lines(["*1 xfailed*"])
651+
572652

573653
class TestXFailwithSetupTeardown:
574654
def test_failing_setup_issue9(self, testdir):

0 commit comments

Comments
 (0)