I have a global object in my main file
# reporter.py
from os import environ
from influxdb import InfluxDBClient
influxdb_client = InfluxDBClient(host=environ['INFLUXCLOUD_HOST'],
username=environ['INFLUXCLOUD_USERNAME'],
password=environ['INFLUXCLOUD_PASSWORD'],
ssl=True,
timeout=4*60)
def foo():
pass
I'm using pytest and I want to set faux values to these environment variables. I have the following in my conftest.py:
# conftest.py
import pytest
@pytest.fixture(scope='session', autouse=True)
def setup_env(monkeypatch):
monkeypatch.setenv('INFLUXCLOUD_HOST', 'host')
monkeypatch.setenv('INFLUXCLOUD_USERNAME', 'username')
monkeypatch.setenv('INFLUXCLOUD_PASSWORD', 'password')
However, when I import reporter
in my test file, I get a KeyError
that INFLUXCLOUD_HOST is missing in the env.
Why does not pytest execute the setup_env
and monkeypatch my environment? Is there a way to do so?
The problem here lies in misunderstanding what the session-scoped fixture is.
To know which tests & autoused fixtures do exist, pytest needs to import the test files & conftest plugins. Then it scans the imported modules, and looks for the fixtures & test functions & test classes & etc. This is called "collection" in pytest terms.
Only after all tests are collected, pytest decides to execute them, and arranges the execution plan, and specifically when the fixtures are prepared. The session-scoped fixtures are prepared first and teared down last — before any tests start, and after all tests have finished.
However, importing of the test files & conftest assumes the execution of these modules — as importing of any other Python module, unrelated to pytest.
So, when you do import reporter
from your test file, or even if you put that global variable directly to your test file, this module is executed, and it attempts to use the env vars. But the fixtures are not yet executed (and pytest does not know about their existence yet). Therefore, it fails.
Even if you will import reporter
from inside of the test function, this will not help much, as pytest may try to import that reporter.py
module before during the collection stage. Pytest would filter it out due to the absence of the test functions/classes, but the import attempt will be done and will fail.
The best solution here is to "pack" the client into a fixture and use that fixture instead of the global variable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With