DiscOH
DiscOH

Reputation: 187

Can pytest run a test iff another fails?

I have a situation where I can do a very fast validation check on an entire object, and if that check passes the object is guaranteed to be healthy. If it fails, I need to identify the aspects that are problematic using time intensive checks.

I was hoping for something like: "@pytest.mark.dependency(depends=["test_a"])" except instead of only running on success it would only run on a failure.

Upvotes: 3

Views: 1528

Answers (1)

hoefling
hoefling

Reputation: 66531

As you pointed out correctly, pytest-dependency is unable to handle your case because it skips tests on failure and not on success. However, with some customizing of this plugin, you can get the desired result. Example:

# conftest.py

import pytest
from pytest_dependency import DependencyManager


def pytest_collection_modifyitems(session, config, items):
    modules = (item.getparent(pytest.Module) for item in items)
    marked_modules = {m for m in modules if m.get_closest_marker('depend_on_failures')}
    for module in marked_modules:
        module.dependencyManager = FailureDepManager()


class FailureDepManager(DependencyManager):

    def checkDepend(self, depends, item):
        for i in depends:
            if i in self.results:
                if self.results[i].isSuccess():
                    pytest.skip('%s depends on failures in %s' % (item.name, i))
                    break

FailureDepManager is the custom version of pytest-dependency's DependencyManager that will skip dependent tests only when the dependency succeeds (has result passed or XPASS). Sadly, this behaviour can only be triggered on a per-module basis as this a current limitation of the plugin (see this question for more details on that). Example usage:

import pytest

pytestmark = pytest.mark.depend_on_failures


@pytest.mark.dependency()
@pytest.mark.xfail(reason='simulate failing test')
def test_foo():
    assert False


@pytest.mark.dependency(depends=['test_foo'])
def test_bar():
    assert True

Due to the mark depend_on_failures on module level, test_bar will now run if test_foo fails:

================================== test session starts ==================================
platform linux -- Python 3.7.0, pytest-4.0.1, py-1.7.0, pluggy-0.8.0
...
plugins: dependency-0.3.2
collected 2 items                                                                           

test_spam.py::test_foo xfail
test_spam.py::test_bar PASSED

========================== 1 passed, 1 xfailed in 0.08 seconds ==========================

Upvotes: 3

Related Questions