pytest-dev / pytest-dev/pytest

add `run` parameter to `pytest.xfail()`

Open
#9,027 10 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

type: proposal
Dominant language
Python
Stars
14.5k
Forks
3.4k
Avg merge
2d 9h
Merged PRs (30d)
35

Description

What's the problem this feature will solve?

The marker pytest.mark.xfail() still runs the tests, but the test results in XFAIL if fail, XPASS if pass.
The API function pytest.xfail() stops execution of the test immediately and the test results in XFAIL.
This is surprising behavior, and not mentioned on https://docs.pytest.org/en/6.2.x/reference.html#pytest-xfail

There is a workaround, described at https://github.com/pytest-dev/pytest/issues/6300.
The workaround is to replace:

def test_foo():
    if runtime_condition:
        pytest.xfail(reason='reasons')
    assert 1 == 1 # doesn't run

with:

def test_foo(request):
    if runtime_condition:
        request.node.add_marker(pytest.mark.xfail(reason='reasons'))
    assert 1 == 1 # does run

However, the workaround is rather clunky.

Describe the solution you'd like

I'd like to see:

  1. Add a run parameter, defaulted to False, to pytest.xfail().
  2. Add a xfail_run_default option to change the default for a test suite by setting this to True in pytest.ini.
  3. Update the API overview to explicitly tell people that the default is to stop execution.
  4. Also tell people in the API overview that the default will change in a future release.
  5. Deprecate the old behavior.
  6. Change the default to True in a future pytest release.

I think the behavior of stopping execution was accidental and not intentionally designed.
It is weird to have the mark and the API function behave so differently.

With the new parameter, the example above could be written as:

def test_foo():
    if runtime_condition:
        pytest.xfail(run=True, reason='reasons')
    assert 1 == 1 # does run

Or by setting xfail_run_default=True in pytest.ini:

[pytest]
xfail_run_default = True
Alternative Solutions
  • An alternative solution is listed above, with the request.node.add_marker(pytest.mark.xfail(reason='reasons')) method.
  • An alternate final solution would be to just do steps 1-3 and not deprecate anything.
  • Also, obviously, the names run and xfail_run_default could be changed if there are better names.
  • A final alternative would be to call the current behavior a defect and just change it.
Additional context

One thing to keep in mind is that --runxfail already exists to "report the results of xfail tests as if they were not marked".
This is a great flag. However, it does confuse the issue here a bit, as the natural option for my feature would be run_xfail, which is confusingly close to --runxfail with a completely different intent.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the pytest.xfail() implementation and its existing tests, then inspect the API overview and pytest.ini option handling. Define the behavior for the run parameter, the suite-level default, deprecation, and future default change; the work is done when tests cover these cases and the API documentation explains the current and planned behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
documentation, testing
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.