11

I want to use the python dotenv-lib at my python project. My dev-environment should use .env-file and the test-suite (pytest) should use .env.test automatically.

Until now I didn't find a satisfying solution.

I'm not very familiar with python. Maybe somebody can point me in the right direction.

Should I load the .env.test file in a pytest hook?

wuarmin
  • 3,274
  • 3
  • 18
  • 31

4 Answers4

18

For anyone coming in 2019 or later:

You can use pytest-dotenv .

jnns
  • 5,148
  • 4
  • 47
  • 74
Lual
  • 2,848
  • 1
  • 20
  • 27
  • 1
    This should be the accepted answer. Worked perfectly. – Kaspar Poland Aug 17 '21 at 03:40
  • 1
    Warning to Django Users: If you're using django-dotenv to call `dotenv.read_dotenv()` from your manage.py module, this library will break it. This library requires python-dotenv, which also uses the 'dotenv' namespace, and you'll end up a ModuleNotFoundError when manage.py is run. – GlenVaughan Nov 17 '22 at 20:37
  • 1
    while this may work, it is unclear to someone unfamiliar with pytest config on how to use it - even their code doesn't outline this, they just assume you know – ProsperousHeart Feb 16 '23 at 15:03
6

After some investigation I came to the conclusion of not using python-dotenv. I ended up using the cool library simple-settings and pytest hooks. It solves my requirements quite well! simple-settings can load settings from several file-types. Which setting-file is loaded can be decided through an environment variable.

Following post can be very helpful, if somebody wants to learn something about pytest and its conftest file: In py.test, what is the use of conftest.py files?

Here's my conftest.py file with two hooks implemented:

import os

def pytest_configure(config):
  os.environ['SIMPLE_SETTINGS'] = 'config.test'
  return config

def pytest_unconfigure(config):
  os.environ['SIMPLE_SETTINGS'] = 'config.development'
  return config

If I run some test with pytest the corresponding environment variable is set. So my test-suite uses automatically the right settings.

wuarmin
  • 3,274
  • 3
  • 18
  • 31
0

I would use setUpClass() method to do it, which gets loaded before individual tests are run.

    class TestCases(Testcase):
    
        @classmethod
        def setUpClass(cls):
            from dotenv import load_dotenv
            load_dotenv(".dev-env")
    
        def test_myrandomtest():
            self.assert(something,something, "Oh crap")
Austin p.b
  • 465
  • 7
  • 13
0

In 2023, while pytest-dotenv is super helpful because it just works, I feel like it's a bit overkill since most projects probably already have python-dotenv installed. As a result, using a conftest.py file to setup a pytest fixture that loads your .env file can be done in 3 fairly simple steps!

Steps

  1. Add a conftest.py file to your tests folder
  2. Import pytest and from dotenv import load_dotenv, find_dotenv
  3. Define a pytest fixture
    @pytest.fixture(scope='session', autouse=True)
    def load_env():
        env_file = find_dotenv('.env.tests')
        load_dotenv(env_file)

This pytest fixture works thanks to two key pieces.

First, setting the scope to session as well as autouse=True ensures this fixture runs before anything else.

Second, using find_dotenv(file_name) ensures the correct file path is used in load_dotenv(file_path) no matter what you call your .env file. If you do happen to call your test env file .env, then you can drop the find_dotenv() call and just run load_dotenv() without any arguments. python-dotenv should have no problem finding any typical .env files via load_dotenv()

That's it! Hopefully this helps, especially those that don't want to install another package to their project!

Nick C
  • 141
  • 1
  • 5