Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to parametrize a Pytest fixture

Tags:

python

pytest

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?

like image 221
Kurt Peek Avatar asked Feb 14 '17 14:02

Kurt Peek


People also ask

How do you parameterize a pytest fixture?

You can use such a simple parametrized fixture for more complex fixtures by combining the param value with some kind of factory. You can also alias the call to parametrize: numbers = pytest. mark.

Can fixture accept multiple parameters?

Generally, the parameter can be any object, so you can always put your fixture parameters in a suitable object. With a tuple or a list parameter, you can also access the values per index as in your example.

Can fixtures have parameters pytest?

You can pass arguments to fixtures with the params keyword argument in the fixture decorator, and you can also pass arguments to tests with the @pytest.


1 Answers

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.

like image 134
imiric Avatar answered Sep 24 '22 00:09

imiric