Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ Tarcisio Fischer
Tareq Alayan
Tatiana Ovary
Ted Xiao
The-Habib
Terje Runde
Thomas Grainger
Thomas Hisch
Expand Down
1 change: 1 addition & 0 deletions changelog/14839.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:func:`pytest.mark.skipif` now validates its keyword arguments and raises a :xcp:`TypeError` when unexpected keyword arguments (such as ``strict``) are passed.
8 changes: 8 additions & 0 deletions src/_pytest/skipping.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ class Skip:
def evaluate_skip_marks(item: Item) -> Skip | None:
"""Evaluate skip and skipif marks on item, returning Skip if triggered."""
for mark in item.iter_markers(name="skipif"):
unexpected_kwargs = set(mark.kwargs) - {"condition", "reason"}
if unexpected_kwargs:
unexpected = sorted(unexpected_kwargs)[0]
msg = f"skipif() got an unexpected keyword argument {unexpected!r}"
if unexpected == "strict":
msg += " - maybe you meant pytest.mark.xfail?"
raise TypeError(msg)

if "condition" not in mark.kwargs:
conditions = mark.args
else:
Expand Down
31 changes: 30 additions & 1 deletion testing/test_skipping.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def test_marked_one_arg_with_reason(self, pytester: Pytester) -> None:
item = pytester.getitem(
"""
import pytest
@pytest.mark.skipif("hasattr(os, 'sep')", attr=2, reason="hello world")
@pytest.mark.skipif("hasattr(os, 'sep')", reason="hello world")
def test_func():
pass
"""
Expand All @@ -70,6 +70,35 @@ def test_func():
assert skipped
assert skipped.reason == "hello world"

def test_marked_skipif_unexpected_kwarg(self, pytester: Pytester) -> None:
item = pytester.getitem(
"""
import pytest
@pytest.mark.skipif("hasattr(os, 'sep')", invalid=123, reason="hello world")
def test_func():
pass
"""
)
with pytest.raises(
TypeError, match=r"skipif\(\) got an unexpected keyword argument 'invalid'"
):
evaluate_skip_marks(item)

def test_marked_skipif_strict_kwarg(self, pytester: Pytester) -> None:
item = pytester.getitem(
"""
import pytest
@pytest.mark.skipif(True, strict=True, reason="hello world")
def test_func():
pass
"""
)
with pytest.raises(
TypeError,
match=r"skipif\(\) got an unexpected keyword argument 'strict' - maybe you meant pytest.mark.xfail\?",
):
evaluate_skip_marks(item)

def test_marked_one_arg_twice(self, pytester: Pytester) -> None:
lines = [
"""@pytest.mark.skipif("not hasattr(os, 'murks')")""",
Expand Down