Search code examples
pythonpython-3.xpytestfixtures

pytest reuse fixture between projects


I want to create fixtures as library components.

A standard test database config is useful for several projects in different repos. It is currently copy/pasted into each independent project as they can't share a config.py.

I refactored the code into a pip installable library but can't work out an elegant way to use it in each project. This doesn't work:

import my_db_fixture

@pytest.fixture
def adapted_db_fixture(my_db_fixture):
    # adapt the test setup

For the real code, the fixture I want to re-use is built from other fixtures. The best work-around I can find so far is to create a local conftest.py as copy/paste code but limited to importing functions and calling them in local fixture functions. I don't like copy/paste and unnecessarily exposes the inner workings of the fixtures.


Solution

  • It is possible to re-use fixtures from an installed library.

    Define the fixtures as usual in the installable package. Then import them into a conftest.py local to the project. You need to import not just the fixture you want but also all fixtures it depends on and (if used) pytest_addoption

    from my.package import (
        the_fixture_i_want,
        all_fixtures_it_uses,
        pytest_addopt
    )
    

    I also discovered you can't un-decorate a library function with a teardown and call it in the local conftest.py:

    # This doesn't work
    
    # pip installed my_fixture.py
    def my_fixture(dependencies)
        # setup code
        yield fixture_object
        # teardown code
    
    # local conftest.py
    import pytest
    import my_fixture  # NB: the module
    
    @pytest.fixture
    def my_fixture(dependencies):
        my_fixture.my_fixture()
        # teardown code isn't called: pytest knows the function has no yield
        # but doesn't realise it's returning a generator none the less
    

    This article helped me:

    peterhurford/pytest-fixture-modularization.md

    I reckoned pytest should recognise something returning a generator as a generator so logged it as a bug. I imagine comments responding to it could be useful:

    call_fixture_func should test the return value not the function