Pytest: Fixture autouse and module imports in test suite (question)

Created on 19 Jun 2018  路  4Comments  路  Source: pytest-dev/pytest

I am having a hard time writing some tests for an application. Basically I have an autouse fixture in conftest.py that sets up some environment variables that the application needs to initialize some objects:

# conftest.py

@pytest.fixture(autouse=True)
def env_config(monkeypatch):
    monkeypatch.setenv('ACCESS_KEY_ID', '12313221323')
    monkeypatch.setenv('SECRET_ACCESS_KEY', '12313221323')
    monkeypatch.setenv('REGION', '12313221323')
    # ...

The problem is that this fixture is only run until _each_ test starts. However, in a specific test file, I am importing the module that contains functions I want to test, _outside_ the tests:

# test_my_func.py
import app


class TestMyFunc:

    def test_foo_(self):
        # Test something about app.foo
        pass

Importing app crashes because the environment variables are not set _yet_:

# app.py
from requests_aws4auth import AWS4Auth


awsauth = AWS4Auth(
    ACCESS_KEY_ID,
    SECRET_ACCESS_KEY,
    REGION,
    'es'
)


def foo():
    pass

I cannot use a blank string as a fallback for os.getenv since AWS4Auth fails when using them.

If I move import app inside the test, everything works perfectly since the autouse fixture has already been executed.

Would appreciate some advice.

question

Most helpful comment

You may also find pytest-env useful. Here's an example where I've used it. It'll set up these environment variables before your test suite is imported

All 4 comments

GitMate.io thinks possibly related issues are https://github.com/pytest-dev/pytest/issues/1050 (provide dependency-tested autouse fixtures), https://github.com/pytest-dev/pytest/issues/2861 (Question re: order of execution of test fixtures), https://github.com/pytest-dev/pytest/issues/668 (autouse fixtures break scope rules), https://github.com/pytest-dev/pytest/issues/2992 (Already imported module), and https://github.com/pytest-dev/pytest/issues/1057 (Pytest fail when autouse fixture is applied and --doctest-modules is set).

Hi @BigChief45,

One approach is changing your application to a fixture, specially if it provides functionality that your tests need (login, endpoints, etc). This fixture should then depend on env_config, which will make env_config execute first.

# conftest.py
import pytest

@pytest.fixture
def app(env_config):
    import app
    return app.App()     

If your app.py just initializes some globals and doesn't provide any functionality, then one way would be to move the initialization code from import time to a function:

# app.py
from requests_aws4auth import AWS4Auth

def startup():
    awsauth = AWS4Auth(
        ACCESS_KEY_ID,
        SECRET_ACCESS_KEY,
        REGION,
        'es'
    )


def foo():
    pass

This way you have more control when setup gets called, so you can move the setup call into the env_config fixture after monkeypatching the environment vars (which probably should be renamed to something more appropriate like app_setup). Of course, your actual "main" entry point now needs to call setup explicitly instead of just importing app, but I believe this is for the best as it is usually recommended to do too much stuff at import time.

Hope this helps!

You may also find pytest-env useful. Here's an example where I've used it. It'll set up these environment variables before your test suite is imported

@nicoddemus Thanks for the suggestion. This approach works very well!

@asottile Looks nice, I'll be sure to try it thanks!

Closing issue.

Was this page helpful?
0 / 5 - 0 ratings