Consider the following Pytest:
import pytest
class TimeLine(object):
instances = [0, 1, 2]
@pytest.fixture
def timeline():
return TimeLine()
def test_timeline(timeline):
for instance in timeline.instances:
assert instance % 2 == 0
if __name__ == "__main__":
pytest.main([__file__])
The test test_timeline
uses a Pytest fixture, timeline
, which itself has the attribute instances
. This attribute is iterated over in the test, so that the test only passes if the assertion holds for every instance
in timeline.instances
.
What I actually would like to do, however, is to generate 3 tests, 2 of which should pass and 1 of which would fail. I've tried
@pytest.mark.parametrize("instance", timeline.instances)
def test_timeline(timeline):
assert instance % 2 == 0
but this leads to
AttributeError: 'function' object has no attribute 'instances'
As I understand it, in Pytest fixtures the function 'becomes' its return value, but this seems to not have happened yet at the time the test is parametrized. How can I set up the test in the desired fashion?
This is actually possible via indirect parametrization.
This example does what you want with pytest 3.1.2:
import pytest
class TimeLine:
def __init__(self, instances):
self.instances = instances
@pytest.fixture
def timeline(request):
return TimeLine(request.param)
@pytest.mark.parametrize(
'timeline',
([1, 2, 3], [2, 4, 6], [6, 8, 10]),
indirect=True
)
def test_timeline(timeline):
for instance in timeline.instances:
assert instance % 2 == 0
if __name__ == "__main__":
pytest.main([__file__])
Also see this similar question.