I'm looking forward to do something similar to the solution described here: Can I parameterize a pytest fixture with other fixtures?

But in my use case I want to have a dynamic number of tests based on a query in a database. In order to do the query I need first the server which is defined by another session fixture.

So, my issue is that I can not find a way of passing the fixture of server to a static function to return directly the collection.


import pytest


@pytest.fixture(scope="session")
def server():
    """
    Fixture that is in global configuration of many tests
    """
    return "some_ip"


def function_based_on_server(server):
    """
    #External function that return the list of tests, for example a query
    """
    if server == "some_ip":
        return [1, 2, 3, 4, 5]

    return [1, 2, 3]


@pytest.fixture
def my_test(server, request):
    """
    Fixture that I want to return my tests
    """
    # request is actually not needed
    return function_based_on_server(server)


@pytest.mark.parametrize('my_test', [x for x in range(2)], indirect=True)
def test_me(my_test):
    # i want this my test to be 1, then 2...
    print(f"\n{my_test}")
    assert my_test == 1

In this example I make use of an artificial loop that returns two tests. But what I actually want is that loop to be something that depends on the server fixture, so that 5 tests are run, giving each time to the variable my_test a value from 1 to 5, instead of a list like in this example.

Thank you.

1

There are 1 best solutions below

0
On

I will provide a solution that may work for some people doing the same, although it does not solve my problem:

def pytest_generate_tests(metafunc):
    """
    Overwrite the pytest hook during test collection to parametrize the tests that have the fixture
    my_parametrized_test_fixture
    """
    if "my_global_fixture" in metafunc.fixturenames:
        my_global_fixture = metafunc.config.getoption("my_global_fixture")
        if my_global_fixture is None:
            raise ValueError("The my_global_fixture is not defined")
        some_collection = asyncio.run(some_function_that_depends_on_the_fixture(my_global_fixture))
        metafunc.parametrize(
            "my_parametrized_test_fixture", some_collection)

Having something like this, overwriting that hook with a different fixture in each test seems to produce the expected result.

The problems:

  • It does not work with pytest-xdist so I can not run tests in parallel, so it is not an option for me.
  • If you skip the test, it will still need to run the some_function_that_depends_on_the_fixture which could be a function that takes a long time and does not allow to run single tests quickly.