Move fixtures.py::add_funcarg_pseudo_fixture_def to Metafunc.parametrize by sadra-barikbin · Pull Request #11220 · pytest-dev/pytest (original) (raw)

After reading your comment and looking more closely at the issue_519.py file, I think I understood some things:


First, I'm really not used to the pytest_generate_tests hook, so I rewrote the test using pytest.mark.parametrize. I also changed some of the names to make things clearer to me:

Rewritten issue_519.py

import pprint from typing import List from typing import Tuple

import pytest

@pytest.fixture(scope="session") def checked_order(): order: List[Tuple[str, str, str]] = []

yield order
pprint.pprint(order)

@pytest.fixture(scope="module") def fixmod(request, a, checked_order): checked_order.append((request.node.name, "fixmod", a)) yield "fixmod-" + a

@pytest.fixture(scope="function") def fixfun(request, fixmod, b, checked_order): checked_order.append((request.node.name, "fixfun", b)) yield "fixfun-" + b + fixmod

@pytest.mark.parametrize("b", ["b1", "b2"], scope="function") @pytest.mark.parametrize("a", ["a1", "a2"], scope="module") def test_one(fixfun, request): print() # print(request._pyfuncitem.nodeid, request._pyfuncitem.callspec)

@pytest.mark.parametrize("b", ["b1", "b2"], scope="function") @pytest.mark.parametrize("a", ["a1", "a2"], scope="module") def test_two(fixfun, request): print() # print(request._pyfuncitem.nodeid, request._pyfuncitem.callspec)

This made me realize that the apparent niceness of the previous ordering, which orders test_one[arg1v1-arg2v1] next to test_two[arg1v1-arg2v1], thus saving a setup, is pretty arbitrary. This can be shown by making the values of the function-scoped parameter (arg2/b) different in test_one and test_two:

-@pytest.mark.parametrize("b", ["b1", "b2"], scope="function") +@pytest.mark.parametrize("b", ["b11", "b12"], scope="function") @pytest.mark.parametrize("a", ["a1", "a2"], scope="module") def test_one(fixfun, request): print() # print(request._pyfuncitem.nodeid, request._pyfuncitem.callspec)

-@pytest.mark.parametrize("b", ["b1", "b2"], scope="function") +@pytest.mark.parametrize("b", ["b21", "b22"], scope="function") @pytest.mark.parametrize("a", ["a1", "a2"], scope="module") def test_two(fixfun, request): print()

The ordering stays the same, which now doesn't make sense.


I also figured that the entire param_index thing was much more useful/natural in the pre-parametrize times, when only pytest_generate_tests/metafunc was used for parametrizing. With pytest_generate_tests you often use the same parameter set for different tests, as is done in the issue_519.py file. But with parametrize, which is mostly done for a single test-function only, it is much less common, I think.