Search code examples
pytestparametrized-testing

pytest parametrize global variable as argument


I'm trying to run the same test for a series of arguments using @pytest.mark.parametrize. The test data must be computed dynamically, which I attempted as follows:

data = [("1", "2")]

@pytest.fixture(scope="class")
def make_data():
    global data

    data.append(("3", "4"))

@pytest.mark.usefixtures("make_data")
class Tester:

    @pytest.mark.parametrize("arg0, arg1", data)
    def test_data(self, arg0, arg1):
        print(arg0, arg1)
        print(data)
        assert 0

I'm creating the data in the class scope fixture and then using it as the parameter set for test_data. I expect test_data to run twice, with arguments 1, 2 and 3, 4, respectively. However, what I get is a single test with arguments 1, 2 and the following stdout:

1 2
[('1', '2'), ('3', '4')]

The value of data is obviously [('1', '2'), ('3', '4')], which means that the class scoped fixture initialized it as I wanted. But somehow it appears that parametrization already happened before this.

Is there a cleaner way to achieve what I want? I could simply run a loop within the test_data method, but I feel like this defies the purpose of parametrization.

Is there a way to return data in the make_data fixture and use the fixture in @pytest.mark.parametrize? When using @pytest.mark.parametrize("arg0, arg1", make_data) I get TypeError: 'function' object is not iterable. make_data must be a fixture, because in the real test case it relies on other fixtures.

I am new to pytest and would be grateful for any hints. Thank you.

EDIT

To provide an explanation on why I'm doing what I'm doing: the way I understand, @pytest.mark.parametrize("arg0, arg1", data) allows parametrization with a hard-coded data set. What if my test data is not hard-coded? What if I need to pre-process it, like I tried in the make_data method? Specifically, what if I need to read it from a file or url? Let's say I have 1000 data samples for which to run the test case, how can I be expected to hard-code them?

Can I somehow use a function to generate the data argument in @pytest.mark.parametrize("arg0, arg1", data)? Something like:

def obtain_data():
    data = []
    # read 1000 samples
    # pre-process
    return data

@pytest.mark.parametrize("arg0, arg1", obtain_data())

This produces an error.


Solution

  • As it turns out, the pytest-cases provides the option to define cases for the parametrization by functions, which helped a great deal. Hope this helps everyone who's looking for something similar