pytest-dependency
pytest-dependency copied to clipboard
Conditional dependency on 2 tests
Is there a way to have a test that is conditional dependent on 2 tests? We have 2 tests (test_1 and test_2) that are mutually exclusive; we control which test to run by using a marker. We have a test which should depend on either one of them. Is there a way to achieve it?
Pseudo code of what is needed:
@pytest.mark.dependency()
def test_1():
return
@pytest.mark.dependency()
def test_2():
return
@pytest.mark.dependency(depends="test_1" or "test_2")
def test_3():
return
This is not supported out of the box. But you can implement it using a small helper function:
import pytest
from pytest_dependency import depends
def depends_or(request, other, scope='module'):
"""Add dependency on any of the other tests.
Call pytest.skip() unless a successful outcome of any of the tests
in `other` has been registered previously. This helper is similar
to `pytest_dependency.depends()`. It takes the same arguments.
But while `pytest_dependency.depends()` combines the tests in
`other` in an and-like manner, it skips the current test unless
all other tests did succeed, this function combines them in an
or-like manner, it runs the current test if at least one of the
other tests did succeed.
"""
item = request.node
for o in other:
try:
depends(request, [o], scope)
except pytest.skip.Exception:
continue
else:
return
pytest.skip("%s depends on any of %s" % (item.name, ", ".join(other)))
@pytest.mark.dependency()
def test_ap():
pass
@pytest.mark.dependency()
@pytest.mark.xfail(reason="deliberate fail")
def test_ax():
assert False
@pytest.mark.dependency()
def test_bp():
pass
@pytest.mark.dependency()
@pytest.mark.xfail(reason="deliberate fail")
def test_bx():
assert False
@pytest.mark.dependency()
def test_c(request):
depends_or(request, ["test_ax", "test_bx"])
pass
@pytest.mark.dependency()
def test_d(request):
depends_or(request, ["test_ax", "test_bp"])
pass
@pytest.mark.dependency()
def test_e(request):
depends_or(request, ["test_ap", "test_bx"])
pass
@pytest.mark.dependency()
def test_f(request):
depends_or(request, ["test_ap", "test_bp"])
pass
Tests test_c
, test_d
, test_e
, and test_f
all depend on either test_a
or test_b
in the manner you described. I included succeeding and failing incarnations of test_a
and test_b
to demonstrate the effect. Only test_c
will be skipped, because both tests in its dependency list fail, the other ones are run, because they have at least on succeeding test in their dependency list.
Warning: as usual, the documentation of internal data structures in pytest is scarce. It is not documented at all that skipping of tests internally work by raising a Skipped
exception and this exception class is exposed in the pytest.skip.Exception
attribute of pytest.skip()
. As usual I needed to find out by reading the pytest source code. There is thus no guarantee that this is stable across pytest versions and I did not check whether it works with all versions supported by pytest-dependency.
Great, will try it out. Thank you