3 Simple Ways To Define Environment Variables In Pytest
When writing Python code, you’ve likely used environment variables to pass configuration or other data to your code at runtime.
Specifying environment variables in Python is easy, but when it comes to testing, things can get a bit tricky.
You need to understand variable preference, how to override them, and how to ensure your tests are isolated from the local runtime environment.
So how do you define environment variables in Pytest? Should you use a .env
file, fixtures, specify them for each test?
Well, in this article you’re going to learn how to define environment variables in Pytest.
We’ll look at examples and discuss the pros and cons of each method so you can choose one that works best for your use case.
Let’s get started, shall we?
Why Use Environment Variables
So what’s the deal and why should you even use environment variables?
Environment variables are a great way to pass configuration information to your code at runtime. They are easy to set, secure, and can be used across different environments.
For example, if you need to access an external value, like ACCOUNT_ID, API_ENDPOINT, or DEPLOYMENT_STAGE, you can define these as environment variables.
You’ll often see parameters like database config, API keys, or other sensitive information (encrypted) passed as environment variables.
They are typically defined in Python using the os
module.1
2
3
4import os
os.environ["ACCOUNT_ID"] = "1234"
account_id = os.getenv("ACCOUNT_ID")
Although basic enough, let’s see how to access these in Pytest.
How To Set Environment Variables In Pytest
Let’s look at a few ways to set Environment Variables in your Unit Tests.
Define Env Vars In The Test (Basic)
The most basic and straightforward way is to define the environment variables in your test file or within the test itself.
Let’s look at an example.
tests/test_env_vars.py
1
2
3
4
5
6
7
8
9
10
11
12import os
# Manually Define Env Variables in Test
os.environ["DEPLOYMENT_STAGE"] = "prod"
os.environ["API_ENDPOINT"] = "https://api.prod.example.com"
os.environ["ACCOUNT_ID"] = "123456789"
def test_load_env_vars():
assert os.environ["DEPLOYMENT_STAGE"] == "prod"
assert os.environ["API_ENDPOINT"] == "https://api.prod.example.com"
assert os.environ["ACCOUNT_ID"] == "123456789"
Running this,1
pytest tests/test_env_vars.py
While easy to understand, this method is
- Ugly
- Not scalable (imagine you had 100s of env variables)
- Not reusable (imagine you had 100s of tests).
Although basic, it’s still a popular way for small scale testing.
Use The python-dotenv
or pytest-dotenv
Package (Better)
The python-dotenv
package is a popular way to define environment variables in a .env
file and load them into your code.
Similarly you can also use the pytest-dotenv
package.
Let’s look at an example.
First, install the package.1
pip install python-dotenv
Next, create a .env
file in the tests
directory.
tests/.env
1
2
3DEPLOYMENT_STAGE=dev
API_ENDPOINT=https://api.dev.example.com
ACCOUNT_ID=987654321
Lastly, access the environment variables in your test.
tests/test_env_vars_env_file.py
1
2
3
4
5
6
7
8
9
10import os
from dotenv import load_dotenv
load_dotenv() # take environment variables from .env
def test_env_vars_from_env_file():
assert os.environ["DEPLOYMENT_STAGE"] == "dev"
assert os.environ["API_ENDPOINT"] == "https://api.dev.example.com"
assert os.environ["ACCOUNT_ID"] == "987654321"
Running this,1
pytest tests/test_env_vars_env_file.py
Using the python-dotenv
package is a cleaner and more scalable way to define environment variables. This package can read .env
files or even load environment variables from a local environment.
However, it’s tough to isolate the test environment from the local environment. For example, if you want to specify environment variables specifically for tests, you’ll need to create several .env
files in different folders.
This can get messy and hard to manage. You can solve that problem with the pytest-env
package.
Use The pytest-env
Package (Best)
The pytest-env
package is a great way to define Environment Variables within your pytest.ini
or pyproject.toml
config file.
If you’re not familiar with pytest-ini
or config files please check out this article for a brief practical overview of the different Pytest config files.
Let’s look at an example.
First, install the package.1
pip install pytest-env
Next, create a pytest.ini
file in the tests
directory.
tests/pytest.ini
1
2
3
4
5[pytest]
env =
DEPLOYMENT_STAGE=staging
API_ENDPOINT=https://api.staging.example.com
ACCOUNT_ID=56789
Lastly, access the environment variables in your test.
tests/test_env_vars_pytest_env.py
1
2
3
4
5
6
7import os
def test_load_env_vars_pytest_env():
assert os.environ["DEPLOYMENT_STAGE"] == "staging"
assert os.environ["API_ENDPOINT"] == "https://api.staging.example.com"
assert os.environ["ACCOUNT_ID"] == "56789"
Instead of pytest.ini
, you can also define these in a pyproject.toml
file.1
2
3
4
5[tool.pytest.ini_options]
env = [
"HOME=~/tmp",
"RUN_ENV=test",
]
The pytest.ini
file also allows you to define environment variables only if not set, for example using the D:
prefix.1
2
3
4[pytest]
env =
D:HOME=~/tmp
D:RUN_ENV=test
Important Note: When running tests, environment variables defined in pytest.ini
file take precedence over a .env
file or local environment during the test execution.
Running this,1
pytest tests/test_env_vars_pytest_env.py
By far, this is the cleanest approach in my opinion. It allows you to define environment variables specifically for your tests and ensures they are isolated from the local environment, without the need to create multiple .env
files.
Conclusion
In this article, you learned a few ways to define environment variables in Pytest.
You explored the most basic way, within the test itself, then moved on to using the python-dotenv
package, and finally the pytest-env
package.
While there is no one size fits all solution, the goal here was to present a few ways, so you can choose the one that best suits your use case.
For a personal side project, it doesn’t matter if you define them within the test itself.
But if you’re writing enterprise-level code, you must be mindful of security and best practices to ensure scalability and maintainability.
If you have ideas for improvement or like for me to cover anything specific, please send me a message via Twitter, GitHub or Email.
Till the next time… Cheers!
Additional Reading
Example Code Used
Python Dotenv Package
Pytest Env Package
What Is pytest.ini
And How To Save Time Using Pytest Config
Pytest Config Files - A Practical Guide To Good Config Management