How to apply fixture from conftest.py to inner folders only

2k Views Asked by At

I have a fixture that located in conftest.py.

@pytest.fixture(scope='module', autouse=True) 
def my_fixture():
    """
    Some useful code
    """

The structure is like below:

tests
 |
 |--first_folder
 |   |--__init__.py
 |   |--test_first_1.py
 |   |--test_first_2.py
 |   
 |--second_folder
 |   |--__init__.py
 |   |--test_second_1.py
 |
 |--__init__.py   
 |--conftest.py
 |--test_common_1.py

I want that fixture to be auto-used in inner folders test scripts only: in test_first_1.py, test_first_2.py, test_second_1.py, but NOT in test_common_1.py.

I can create conftest with that fixture in each inner folder, but I don't want to duplicate the code

Is there any way to apply fixture from conftest to test scripts from inner folders and ignore it in common folder test scripts?

4

There are 4 best solutions below

0
On BEST ANSWER

@lmiguelvargasf answer (+1) pointed me in the right direction and using request I solved the issue as below:

@pytest.fixture(scope='module', autouse=True)
def my_fixture(request):
    if request.config.invocation_dir.basename != 'tests':
        """
        Some useful code
        """

This fixture will be applied only to test-scripts from inner folders as invocation folder name is not equal to 'tests'

1
On

If you want to autouse a top-level conftest fixture for only a subset of your test modules, the guidance is to make use of the global variable pytestmark (reference: pytestmark; tutorial: Marking whole classes or modules).

In your case, you'll want to disable autouse for your fixture defined in tests/conftest.py:

# tests/conftest.py
import pytest

@pytest.fixture(scope='module') 
def my_fixture():
    """
    Some useful code
    """

Then in whatever module you'd like to enable autouse of it, set the global variable pytestmark e.g.

# tests/first_folder/test_first_1.py
import pytest

pytestmark = pytest.mark.usefixtures('my_fixture')

def test_first_feature():
    result = something(my_fixture)  # autouse of my_fixture
    assert result == expected
1
On

You can achive this by moving the folders 'first folder' and 'second folder' to a new folder and have a conftest.py file in that new folder. Like this -

tests
 |
 |--new folder
 |  |--first_folder
 |  |  |--__init__.py
 |  |  |--test_first_1.py
 |  |  |--test_first_2.py
 |  |
 |  |--second_folder
 |  |  |--__init__.py
 |  |  |--test_second_1.py
 |  |--conftest.py
 |
 |--__init__.py   
 |--conftest.py
 |--test_common_1.py
0
On

One possible solution, is you do not want to change the structure of your folders, is that you use the request object in your fixture to check the markers used on the test, so you do anything if a specific marker is set:

@pytest.fixture(scope='module', autouse=True) 
def my_fixture(request):
    """
    Some useful code
    """
    if 'noautofixt' in request.keywords:
        return
    # more code

Then mark your tests as follows:

@pytest.mark.noautofixt
def test_no_running_my_fixture():
    pass