title: pytest modules using os.environ - How do I test it correctly?
body: <p>currently I am writing some Webapp, but this time I want to learn how to write proper tests for it (using pytest) :)</p>
  
  <p>A very common pattern I often see is to make the default configuration changeable using environment variables.
  Currently I am struggling how to test this properly. </p>
  
  <p>I've prepared some demo:</p>
  
  <pre><code>./app
  ./app/conf.py
  ./conftest.py
  ./run.py
  ./tests
  ./tests/test_demo.py
  </code></pre>
  
  <p>My <code>./app/conf.py</code> looks like this:</p>
  
  <pre><code>from os import environ
  
  DEMO = environ.get('DEMO', 'demo')
  TEST = environ.get('TEST', 'test')
  </code></pre>
  
  <p>Launching the <code>./run.py</code> shows that the settings are indeed changeable:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>It prints out <code>not a demo</code> and <code>untested</code> - as expected. Great. (Note that I set the environment variables before importing <code>conf</code>).</p>
  
  <p>Now to the tests: The <code>./conftest.py</code> is currently empty it just helps pytest to locate the modules inside the app folder.</p>
  
  <p>The <code>./tests/test_demo.py</code> contains the following:</p>
  
  <pre><code>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()
  </code></pre>
  
  <p>If I run pytest now, <code>test_conf_changed</code> fails with <code>'demo' == 'tested demo'</code> -> the monkeypatch function did not patch the environment.</p>
  
  <p>If I swap both testing functions (so <code>test_conf_changed</code> runs first), the <code>test_conf_defaults</code> will fail with <code>'tested demo' == 'demo'</code>. </p>
  
  <p>How I interpret it, is - the first time <code>conf</code> gets imported it sticks there with it's initial settings.. </p>
  
  <p>How can I tell pytest to completely reimport <code>conf</code> each test function, <em>after</em> setting up the environment variables?</p>
  
  <p>I am stuck there for two days now - and slowly I doubt if testing is worth the hassle - please prove me wrong :) </p>