This seems like a very basic question, but I looked at https://docs.pytest.org/en/6.2.x/reference.html, which I think is the reference for pytest and couldn't find the answer.
So I wanted to combine a pytest.fixture
(setup/teardown using yield
) with a pytest.mark.parametrize
... and I realised that they both have to be included as parameters in the test function.
A simple experiment showed that it doesn't appear to matter what order they are listed in the list of parameters, so my working assumption currently is that it never matters, and that, also, there are no (optional) named parameters in these methods.
It'd be nice to know if this is actually documented somewhere, and if I've got this right.
This is not explicitly stated, as far as I can see, but follows implicitly from the documentation:
When pytest goes to run a test, it looks at the parameters in that test function’s signature, and then searches for fixtures that have the same names as those parameters. Once pytest finds them, it runs those fixtures, captures what they returned (if anything), and passes those objects into the test function as arguments.
(side note: I generally recommend to check this documentation - it has been reworked recently and is very comprehensive IMO)
Fixtures are always looked up by name, so the order they appear in the argument list should not matter in principle.
This is also true for the arguments given in pytest.mark.parametrize
, as observed.
Generally, the execution order of independent fixtures shall not matter, and if it does, it is either a bug, or the fixtures are not compatible.
There is one caveat: if you use fixtures together with positional parameters introduced by the unittest.mock.patch
or unittest.mock.patch.object
decorators (which are supported by pytest
), the fixture arguments shall always be passed last:
from unittest.mock import patch
@patch("module.class")
def test_correct(mocked_class, capsys):
...
@patch("module.class")
def test_incorrect(capsys, mocked_class):
...
# fails because "mocked_class" is seen as an unknown fixture
This is not surprising, given how positional arguments work.
A way to avoid this is to use pytest-mock
, which provides the mocker
fixture:
def test_correct(mocker, capsys):
mocked_class = mocker.patch("module.class")
...
def test_correct2(capsys, mocker):
mocked_class = mocker.patch("module.class")
...