Pytest: Patching getfuncargnames. Adding fixtures to argnames list

Created on 5 Apr 2020  路  7Comments  路  Source: pytest-dev/pytest

I am writing plug-in for the pytest.
I want to make a hook that will trigger a fixture that is not passed as an argument in test and is not specified in usefixture.
I want to run it after fixture with autouse flag and in front of other fixtures. The condition for launching will be checking for the presence of a custom marker.
It should look like this:

this is an abstract example
```@pytest.fixture
def open_fixture(autouse=True):
open_page()

@pytest.fixture
def filling_fixture():
filling_fields()

@pytest.fixture
def click_fixture():
click_button()

@pytest.mark.my_marker
def test(clik_fixture):
pass

all three fixtures must be started in turn


I decided to change the FixtureDef class attribute and add my fixture to self.argnames.
For this i wanted to make a monkey patch and wrap getfuncargnames

```def custom_getfuncargnames(func):
    def wrapper(*args, **kwargs):
        if [mark.name for mark in func.own_markers if "my_marker" in mark.name]:
            return func(*args, **kwargs).insert("filling_fixure")
    return wrapper

But I can't fix this module. I didn't want to understand what the problem it was, since the monkey patch is not a very good solution. I'm sure pytest has a simpler solution to my problem.

fixtures question

All 7 comments

Wouldn't that be the same as autouse, though?

As an alternative, I've found it very effective to use a common naming scheme for fixtures to make sort of anchor points that I can override and/or request to place a fixture at a certain point in the dependency chain.

For example, if my "last" autouse fixture is always called page, I can just define another autouse fixture that requests page to guarantee that it'll happen before non-autouse fixtures, and after page. Then, if I need to modify what page does, I can override it in the relevant scope so that only that scope is affected by the override. I can even override page and have that new version request page so that it just adds on to whatever page was doing.

@vkutepov a fixture can depend upon another fixture, for example:

```python
@pytest.fixture
def a():
pass

@pytest.fixture
def b(a):
pass
````

鈽濓笍

@symonk
Yes it is. but my fixture "a" is inside the file plugin.py, fixture "b" is in the test that
use this plugin. I did not understand how to make fixture "a" visible for fixture "b" and for this I decided to use monkey patching.

@vkutepov in order for a fixture to be visible to another fixture, it must be defined in the same scope, a parent scope (which considers conftest files), or installed in a plugin. Normally, common fixtures would be placed in conftest files in the appropriate place in the file structure. If you want to go the plugin route, you'll need to make an actual installable plugin and register it with the appropriate pytest entry point. You can check out pytest-django for an example of how to do this.

you can probably also load an internal plugin via pytest_plugins=['']

Thank you, guys. Last time I didn鈥檛 make an scope="session" and the user could not access the fixture from my plugin. Now everything is working.
Sorry for the stupid questions, I'm just getting to know fixture magic.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dmtucker picture dmtucker  路  3Comments

SwampFalc picture SwampFalc  路  3Comments

RonnyPfannschmidt picture RonnyPfannschmidt  路  3Comments

bluenote10 picture bluenote10  路  3Comments

nicoddemus picture nicoddemus  路  3Comments