Playwright Read .env File and Use Environment Variables

Environment variables help you store sensitive information such as URLs, usernames, passwords, API keys, and tokens outside your source code.


Step 1: Install dotenv Package

Playwright does not automatically load .env files, so install the dotenv package.

npm install dotenv

Step 2: Create a .env File

Create a file named .env in the project root directory.

BASE_URL=https://opensource-demo.orangehrmlive.com
USERNAME=Admin
PASSWORD=admin123

Project Structure:

PlaywrightProject/

├── .env
├── playwright.config.ts
├── tests/
└── package.json

Step 3: Load Environment Variables

Open playwright.config.ts.

import { defineConfig } from '@playwright/test';
import dotenv from 'dotenv';

dotenv.config();

export default defineConfig({
use: {
baseURL: process.env.BASE_URL
}
});

Now Playwright can access variables from .env.


Step 4: Use Environment Variables in Tests

Example:

import { test, expect } from '@playwright/test';

test('Login Test', async ({ page }) => {

await page.goto('/');

await page.fill('input[name="username"]', process.env.USERNAME!);

await page.fill('input[name="password"]', process.env.PASSWORD!);

await page.click('button[type="submit"]');

await expect(page.locator('.oxd-topbar-header-title'))
.toContainText('Dashboard');
});

Step 5: Create a Separate Environment Configuration File

Create config/env.ts

import dotenv from 'dotenv';

dotenv.config();

export const env = {
baseUrl: process.env.BASE_URL || '',
username: process.env.USERNAME || '',
password: process.env.PASSWORD || ''
};

Use it in your test:

import { test } from '@playwright/test';
import { env } from '../config/env';

test('Login Test', async ({ page }) => {

await page.goto(env.baseUrl);

await page.fill('input[name="username"]', env.username);

await page.fill('input[name="password"]', env.password);
});

This approach is cleaner and easier to maintain.


Step 6: Use Different .env Files for Different Environments

Create multiple files:

.env.dev
.env.qa
.env.stage
.env.prod

Example:

.env.qa

BASE_URL=https://qa.example.com
USERNAME=qauser
PASSWORD=qapassword

.env.prod

BASE_URL=https://prod.example.com
USERNAME=produser
PASSWORD=prodpassword

Step 7: Load Environment-Specific Files

Create env.ts

import dotenv from 'dotenv';

const environment = process.env.TEST_ENV || 'qa';

dotenv.config({
path: `.env.${environment}`
});

Run tests:

QA

TEST_ENV=qa npx playwright test

Production

TEST_ENV=prod npx playwright test

Step 8: Use Environment Variables in Playwright Config

import { defineConfig } from '@playwright/test';
import dotenv from 'dotenv';

dotenv.config();

export default defineConfig({
use: {
baseURL: process.env.BASE_URL,
headless: process.env.HEADLESS === 'true'
}
});

.env

BASE_URL=https://example.com
HEADLESS=false

Step 9: Use Environment Variables in Custom Fixtures

import { test as base } from '@playwright/test';

export const test = base.extend({
credentials: async ({}, use) => {

await use({
username: process.env.USERNAME,
password: process.env.PASSWORD
});
}
});

Usage:

import { test } from '../fixtures/customFixture';

test('Login', async ({ credentials }) => {

console.log(credentials.username);
console.log(credentials.password);
});

Step 10: Best Practices

✔ Store Sensitive Data in .env

USERNAME=Admin
PASSWORD=admin123
API_KEY=xyz123

✔ Add .env to .gitignore

.env
.env.*

✔ Use Separate Files Per Environment

.env.dev
.env.qa
.env.stage
.env.prod

✔ Create a Centralized Environment Helper

export const env = {
baseUrl: process.env.BASE_URL!,
username: process.env.USERNAME!,
password: process.env.PASSWORD!
};

✔ Validate Required Variables

if (!process.env.BASE_URL) {
throw new Error('BASE_URL is missing');
}

Real-World Framework Structure

project

├── .env.qa
├── .env.prod

├── config
│ └── env.ts

├── fixtures
│ └── customFixture.ts

├── pages
│ └── LoginPage.ts

├── tests
│ └── login.spec.ts

└── playwright.config.ts

This structure is commonly used in enterprise Playwright frameworks because it supports multiple environments, keeps secrets secure, and makes tests easier to maintain.

Leave a Comment