small medium large xlarge

Generic-user-small
02 Oct 2017, 22:34
gabriele (2 posts)

Hi, I would like to ask if there is a best practice to parametrize a fixture in the sense of passing a parameter to it.

The first thing that comes to my mind is that it might not be a good idea at all, maybe fixtures should have no parameters so that they can really be pre-initialized objects that are used as starting points for tests.

But let’s discuss an example I’m facing in a real application:

I would like to create a fixture structure for this object hierarchy: Design -> Site -> Node, meaning that a design can contain sites, and a site can contain nodes.

So this is my fixture structure:

@pytest.fixture
def design():
    ...

@pytest.fixture
def site(design):
   ...

@pytest.fixture
def node(site):
   ...

So I can easily write tests starting from any of these elements and have the “parent” elements managed for free.

The problem: I can have two different kinds of “design” that are created with different parameters while the child objects remain the same. So I would like to be able, in some way, to say: use the designTypeA fixture or designTypeB fixture but also: use the node fixture with a designTypeA o designTypeB parent.

The solutions I found (and why I don’t love them):

  1. One possibility is to duplicate the whole fixture structure and have a

    designTypeA->siteTypeA->nodeTypeA and a designTypeB->siteTypeB->nodeTypeB

    This is so redundant if the hierarchy is big enough

  2. A second possibility is to use “indirect=True” https://stackoverflow.com/a/33879151/1534775 but I dislike the fact that you have to use the @pytest.mark.parametrize decorator with all that parameters, it’s unreadable and doesn’t look like a fixture

  3. The third option is to use introspection to access the request object and leave some sort of flag in the calling test and act accordingly when creating the fixture.

    it’s the option I’ve chosen so far but it feels like a hack

My solution is even more hacked together than a simple flag, I’m basically using the mark decorator (the label) as a flag.

@pytest.fixture
def design(request):
    if request.keywords._marker.get('TypeA'):
        _create_typeA()
    else:
        ....

@pytest.fixture
def site(design):
   ...

@pytest.fixture
def node(site):
   ...

and in the test

@pytest.mark.TypeA
def test_something(design):
    pass

I’d love to hear some else’s opinion on what approach you suggest, if it’s a terrible idea :) or even if it make sense at all.

Thanks!

Generic-user-small
02 Oct 2017, 22:38
gabriele (2 posts)

Even if this is closely related to a chapter of the book I realized after opening the topic that this kind of purely technical question might not be the purpose of this forum, if so feel free to close I’m new to PragProg :)

You must be logged in to comment