Search code examples
pytestskip

Pytest - skip (xfail) mixed with parametrize


is there a way to use the @incremental plugin like described att Pytest: how to skip the rest of tests in the class if one has failed? mixed with @pytest.mark.parametrize like below:

@pytest.mark.incremental
Class TestClass:
  @pytest.mark.parametrize("input", data)
  def test_preprocess_check(self,input):
    # prerequisite for test

  @pytest.mark.parametrize("input",data)
  def test_process_check(self,input):
    # test only if test_preprocess_check succeed

The problem i encountered is, at the first fail of test_preprocess_check with a given input of my data set, the following test_preprocess_check and test_process_check are labeled "xfail". The behaviour i expect will be, at each new "input" of my parametrized data set, the test will act in an incremental fashion.

ex: data = [0,1,2]

if only test_preprocess_check(0) failed:

i got the following report: 1 failed, 5 xfailed

but i expect the report: 1 failed, 1 xfailed, 4 passed

Thanks


Solution

  • After some experiments i found a way to generalize the @incremental to works with parametrize annotation. Simply rewrite the _previousfailed argument to make it unique for each input. The argument _genid was excactly the need.

    I added a @pytest.mark.incrementalparam to achieve this.

    Code become:

    def pytest_runtest_setup(item):
    
        previousfailed_attr = getattr(item, "_genid",None)
        if previousfailed_attr is not None:
            previousfailed = getattr(item.parent, previousfailed_attr, None)
            if previousfailed is not None:
                pytest.xfail("previous test failed (%s)" %previousfailed.name)
    
        previousfailed = getattr(item.parent, "_previousfailed", None)
        if previousfailed is not None:
            pytest.xfail("previous test failed (%s)" %previousfailed.name)
    
    def pytest_runtest_makereport(item, call): 
    
        if "incrementalparam" in item.keywords: 
            if call.excinfo is not None:
                previousfailed_attr = item._genid
                setattr(item.parent,previousfailed_attr, item)
    
        if "incremental" in item.keywords:
            if call.excinfo is not None:
                parent = item.parent
                parent._previousfailed = item
    

    It's interesting to mention that's it can't be used without parametrize cause parametrize annotation creates automatically _genid variable.

    Hope this can helps others than me.