diff --git a/changelog/4497.bugfix.rst b/changelog/4497.bugfix.rst new file mode 100644 index 000000000..f2e71218e --- /dev/null +++ b/changelog/4497.bugfix.rst @@ -0,0 +1 @@ +Fix the crash that occurred when pytest was invoked with `-o empty_parameter_set_mark=xfail` + `--runxfail` diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 32c3ec4b0..5d59286e6 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -346,7 +346,7 @@ def reorder_items_atscope( def get_direct_param_fixture_func(request): - return request.param + return request.param if hasattr(request, "param") else None @attr.s(slots=True, auto_attribs=True) diff --git a/testing/test_skipping.py b/testing/test_skipping.py index 6415480ef..996872e43 100644 --- a/testing/test_skipping.py +++ b/testing/test_skipping.py @@ -680,6 +680,41 @@ class TestXFail: result.stdout.fnmatch_lines(["*1 passed*"]) assert result.ret == 0 + @pytest.mark.parametrize("strict", [True, False]) + def test_runxfail_with_empty_parameter_set_mark_xfail(self, testdir, strict): + testdir.makeini( + """ + [pytest] + xfail_strict = %s + """ + % strict + ) + + p = testdir.makepyfile( + """ + import pytest + + @pytest.mark.parametrize( + ('a', 'b'), + # no cases defined yet + ( + ), + ) + def test(a, b): + assert 1 == 1 + """ + ) + result = testdir.runpytest( + p, "--runxfail", "-o", "empty_parameter_set_mark=xfail" + ) + + result.stdout.fnmatch_lines(["*1 failed*" if strict else "*1 passed*"]) + if strict: + result.stdout.fnmatch_lines( + ["*XPASS(strict)] got empty parameter set ('a', 'b')*"] + ) + assert result.ret == (1 if strict else 0) + @pytest.mark.parametrize("strict_val", ["true", "false"]) def test_strict_xfail_default_from_file( self, pytester: Pytester, strict_val