Skip to content

Fixture autouse and module imports in test suite (question) #3597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
aalvrz opened this issue Jun 18, 2018 · 4 comments
Closed

Fixture autouse and module imports in test suite (question) #3597

aalvrz opened this issue Jun 18, 2018 · 4 comments
Labels
type: question general question, might be closed after 2 weeks of inactivity

Comments

@aalvrz
Copy link

aalvrz commented Jun 18, 2018

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.

@pytestbot pytestbot added the type: question general question, might be closed after 2 weeks of inactivity label Jun 18, 2018
@pytestbot
Copy link
Contributor

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

@nicoddemus
Copy link
Member

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!

@asottile
Copy link
Member

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

@aalvrz
Copy link
Author

aalvrz commented Jun 20, 2018

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

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

Closing issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: question general question, might be closed after 2 weeks of inactivity
Projects
None yet
Development

No branches or pull requests

4 participants