Can I pass arguments to pytest fixtures?
We can do this by using a method that takes args within a fixture and return the method from the fixture.
let me show you an example
@pytest.fixturedef my_fixture(): def _method(a, b): return a*b return _methoddef test_me(my_fixture): result1 = my_fixture(2, 3) assert result1 == 6 result2 = my_fixture(4, 5) assert result2 == 20
Is there a way to pass arguments to a fixture so that those arguments can be used in creating the object the fixture returns? Should I be parameterizing the test function?
You can use test parametrization with indirect=True
.In the pytest docs: Apply indirect on particular arguments. As displayed here: https://stackoverflow.com/a/33879151/3858507
The fixture?
Another option that might suit you is using some fixture that specifies the argument using parametrization:
@pytest.fixture(params=[3,4])def number_of_passengers(request): return request.param
and then accessing this fixture from the taxi and the test itself:
@pytest.fixturedef taxi(number_of_passengers): return Taxi(rear_seat=Passenger() * number_of_passengers)def test_three_passengers_in_taxi(taxi, number_of_passengers) assert taxi.has_passengers(number_of_passengers) assert taxi.front_passenger_is_not_a_child()
This way is good if your tests and asserts are very similar between the cases you have.
Or am I wasting time and is a fixture per test the way to go?
I'd say you definitely shouldn't create a fixture for every test function. For that, you can just put the setup inside the test. This is actually a viable alternative in the case that you have to make different asserts for different cases of the taxi.
And finally another possible pattern you can use is a taxi factory. While for the example you've presented its not quite useful, if multiple parameters are required and only some are changing you can create a fixture similar to the following:
from functools import partial@pytest.fixturedef taxi_factory(): return partial(Taxi, 1, 2, 3)
That fixture
is just a Python decorator.
@decoratordef function(args): ...
is fancy for
def function(args): ...function = decorator(function)
So you just might be able to write your own decorator, wrapping up the function you want to decorate in whatever you need and the fixture
:
def myFixture(parameter): def wrapper(function): def wrapped(*args, **kwargs): return function(parameter, *args, **kwargs) return wrapped return pytest.fixture(wrapper)@myFixture('foo')def function(parameter, ...): ...
This will act like the fixture
but will pass a value ('foo'
) as parameter
to function
.