Test Environment Management
Test environment management is the unglamorous skill that determines whether your automation suite can run reliably in CI. It covers environment variables, secrets management, database seeding, service dependencies, and ensuring your tests have a stable, reproducible environment to run in — regardless of whose machine or CI runner they execute on.
Environment Management Patterns
# ══════════════════════════════════════════════════════════════
# CONFIGURATION MANAGEMENT PATTERN
# All env-specific configuration via environment variables
# ══════════════════════════════════════════════════════════════
# config.py
import os
class TestConfig:
# URLs
BASE_URL = os.getenv("BASE_URL", "https://staging.myapp.com")
API_URL = os.getenv("API_URL", "https://api.staging.myapp.com")
# Credentials (NEVER hardcode — always from environment)
ADMIN_EMAIL = os.getenv("ADMIN_EMAIL", "admin@test.com")
ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD") # No default — must be set
# Test behavior
HEADLESS = os.getenv("HEADLESS", "true").lower() == "true"
BROWSER = os.getenv("BROWSER", "chromium")
TIMEOUT = int(os.getenv("TIMEOUT", "15"))
PARALLEL_WORKERS = int(os.getenv("PARALLEL_WORKERS", "4"))
# Feature flags
SKIP_MOBILE = os.getenv("SKIP_MOBILE", "false").lower() == "true"
SKIP_SECURITY = os.getenv("SKIP_SECURITY", "false").lower() == "true"
@classmethod
def validate(cls):
"""Validate all required env vars are set before tests start"""
required = ["ADMIN_PASSWORD"]
missing = [var for var in required if not os.getenv(var)]
if missing:
raise EnvironmentError(f"Required env vars not set: {missing}")
# conftest.py — call validation at startup:
def pytest_configure(config):
TestConfig.validate()
# ── LOCAL .env FILE (gitignored) ─────────────────────────────
# .env (NOT committed to git):
# BASE_URL=https://localhost:3000
# ADMIN_PASSWORD=local-dev-password
# HEADLESS=false ← See browser locally
# Load .env in local runs:
# pip install python-dotenv
from dotenv import load_dotenv
load_dotenv() # Loads .env file if present
# ── DATABASE SEEDING FOR TESTS ────────────────────────────────
import pytest
import requests
@pytest.fixture(scope="session", autouse=True)
def seed_test_database():
"""Seed test database with required data before all tests"""
admin_token = get_admin_token()
headers = {"Authorization": f"Bearer {admin_token}"}
# Create test users via API
test_users = [
{"email": "qa.user@test.com", "password": "Test@1234", "role": "user"},
{"email": "qa.admin@test.com", "password": "Test@1234", "role": "admin"},
]
for user in test_users:
r = requests.post(f"{TestConfig.BASE_URL}/api/admin/users",
json=user, headers=headers)
if r.status_code not in [201, 409]: # 409 = already exists (OK)
raise Exception(f"Failed to seed user {user['email']}: {r.status_code}")
print(f"✅ Test database seeded with {len(test_users)} users")
yield # Tests run here
# Optional: cleanup seeded data (can also leave it for inspection)Common Mistakes
- Hardcoded URLs in test code — when staging URL changes, you'd have to update dozens of files; always use BASE_URL environment variable
- Storing test credentials in git — credentials must never be committed; use .gitignore for .env files and GitHub Secrets for CI
- No environment validation at startup — failing 2 minutes into a test run because a required env variable is missing is avoidable; validate at conftest startup
- Data seeding in every test — seeding takes time; use session-scoped fixtures to seed once per test run, not once per test
Tip
Tip
Practice Test Environment Management in small, isolated examples before integrating into larger projects. Breaking concepts into small experiments builds genuine understanding faster than reading alone.
Technical diagram.
Practice Task
Note
Practice Task — (1) Write a working example of Test Environment Management from scratch without looking at notes. (2) Modify it to handle an edge case (empty input, null value, or error state). (3) Share your solution in the Priygop community for feedback.
Quick Quiz
Common Mistake
Warning
A common mistake with Test Environment Management is skipping edge case testing — empty inputs, null values, and unexpected data types. Always validate boundary conditions to write robust, production-ready software testing code.
Key Takeaways
- Test environment management is the unglamorous skill that determines whether your automation suite can run reliably in CI.
- Hardcoded URLs in test code — when staging URL changes, you'd have to update dozens of files; always use BASE_URL environment variable
- Storing test credentials in git — credentials must never be committed; use .gitignore for .env files and GitHub Secrets for CI
- No environment validation at startup — failing 2 minutes into a test run because a required env variable is missing is avoidable; validate at conftest startup