Pytest using os.environ - Ho, am I testing it correctly?
I am currently writing several Webapps, but this time I want to learn how to write correct tests for it (using pytest) :)
Very often I often see that you can change the default configuration using environment variables. I am currently struggling how to properly check this.
I have prepared a demo:
./app ./app/conf.py ./conftest.py ./run.py ./tests ./tests/test_demo.py
My ./app/conf.py
looks like this:
from os import environ
DEMO = environ.get('DEMO', 'demo')
TEST = environ.get('TEST', 'test')
Running it ./run.py
shows that the settings are indeed changeable:
from os import environ
environ['DEMO'] = 'not a demo'
environ['TEST'] = 'untested'
from app import conf
if __name__ == '__main__':
print(conf.DEMO)
print(conf.TEST)
It prints not a demo
and untested
- as expected. Fine. (Note that I am setting environment variables before importing conf
).
Now to the tests: ./conftest.py
currently empty, it just helps pytest find modules inside the application folder.
./tests/test_demo.py
contains the following:
def test_conf_defaults():
from app import conf
assert conf.DEMO == 'demo'
assert conf.TEST == 'test'
def test_conf_changed(monkeypatch):
monkeypatch.setenv('DEMO', 'tested demo')
monkeypatch.setenv('TEST', 'demo test')
from app import conf
assert conf.DEMO == 'tested demo'
assert conf.TEST == 'demo test'
monkeypatch.undo()
If I run pytest now, it test_conf_changed
fails 'demo' == 'tested demo'
-> monkeypatch function didn't fix the environment.
If I change both test functions (executed first test_conf_changed
), it test_conf_defaults
will fail 'tested demo' == 'demo'
.
The way I interpret it is - on first login conf
it will import it there with its original settings.
How can I tell pytest to completely reimport conf
each test function after setting environment variables?
I've been stuck there for two days - and I'm slowly doubting testing is worth it to prove I'm wrong :)
source to share
Thanks for the tip, Evert (variables inside the conf-module are set inside the global namespace, they stick). I think I got it now.
To test my code, I have to explicitly specify reimport conf
after setting environment variables. Changing the code in ./tests/test_demo.py
to this does the trick:
from importlib import reload
from app import conf
def test_conf_changed(monkeypatch):
monkeypatch.setenv('DEMO', 'tested demo')
monkeypatch.setenv('TEST', 'demo test')
reload(conf)
assert conf.DEMO == 'tested demo'
assert conf.TEST == 'demo test'
def test_conf_defaults():
reload(conf)
assert conf.DEMO == 'demo'
assert conf.TEST == 'test'
Thank.
source to share