Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pytest and Dynamic fixture modules

Tags:

python

pytest

I am writing functional tests using pytest for a software that can run locally and in the cloud. I want to create 2 modules, each with the same module/fixture names, and have pytest load one or the other depending if I'm running tests locally or in the cloud:

/fixtures
/fixtures/__init__.py
/fixtures/local_hybrids
/fixtures/local_hybrids/__init__.py
/fixtures/local_hybrids/foo.py
/fixtures/cloud_hybrids
/fixtures/cloud_hybrids/__init__.py
/fixtures/cloud_hybrids/foo.py
/test_hybrids/test_hybrids.py

foo.py (both of them):

import pytest
@pytest.fixture()
def my_fixture():
    return True

/fixtures/__init__.py:

if True:
    import local_hybrids as hybrids
else:
    import cloud_hybrids as hybrids

/test_hybrids/test_hybrids.py:

from fixtures.hybrids.foo import my_fixture

def test_hybrid(my_fixture):
   assert my_fixture

The last code block doesn't work of course, because import fixtures.hybrids is looking at the file system instead of __init__.py's "fake" namespace, which isn't like from fixtures import hybrids, which works (but then you cannot use the fixtures as the names would involve dot notation).

I realize that I could play with pytest_generate_test to alter the fixture dynamically (maybe?) but I'd really hate managing each fixture manually from within that function... I was hoping the dynamic import (if x, import this, else import that) was standard Python, unfortunately it clashes with the fixtures mechanism:

import fixtures
def test(fixtures.hybrids.my_fixture):  # of course it doesn't work :)
    ...

I could also import each fixture function one after the other in init; more legwork, but still a viable option to fool pytest and get fixture names without dots.

Show me the black magic. :) Can it be done?

like image 606
Joe Avatar asked Jun 04 '26 04:06

Joe


1 Answers

I think in your case it's better to define a fixture - environment or other nice name.

This fixture can be just a getter from os.environ['KEY'] or you can add custom command line argument like here then use it like here and the final use is here.

What im trying to tell is that you need to switch thinking into dependency injection: everything should be a fixture. In your case (and in my plugin as well), runtime environment should be a fixture, which is checked in all other fixtures which depend on the environment.

like image 158
Anatoly Bubenkov Avatar answered Jun 06 '26 19:06

Anatoly Bubenkov