Захардкодить baseURL в playwright.config.ts: проверенный способ запустить тесты не в том окружении. Кто-то меняет URL, забывает откатить, тесты зеленеют на устаревших данных. Эта статья разбирает: чтение base URL и учётных данных из переменных окружения, загрузку .env-файлов локально, передачу секретов через GitHub Actions и упаковку учётных данных в фикстуры, чтобы отсутствующая переменная падала на старте, а не в середине теста.
Проблема с захардкоженными URL
// плохо — жёстко задан, никакой гибкости
use: {
baseURL: 'https://staging.myapp.com',
},Нужно запустить локально: меняешь URL вручную. CI должен проверить фича-ветку: кто-то вспоминает откатить, кто-то нет. Тесты проходят, но против не того окружения. Ошибка незаметна: всё зелёное, просто данные устаревшие.
Переменные окружения
Берём base URL из переменной окружения:
// playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
use: {
baseURL: process.env.BASE_URL || 'http://localhost:3000',
},
});Запуск:
# локально
npx playwright test
# на staging
BASE_URL=https://staging.myapp.com npx playwright test
# продакшн (только smoke-тесты)
BASE_URL=https://myapp.com npx playwright test --grep @smokeНикаких изменений в коде при смене окружения. Только другая переменная.
dotenv для локальной разработки
Каждый раз писать BASE_URL=... неудобно. Используй .env-файл:
# .env.local
BASE_URL=http://localhost:3000
API_TOKEN=dev-token-abc123
TEST_USER_EMAIL=test@example.com
TEST_USER_PASSWORD=testpass123Загружаем в конфиге:
npm install -D dotenv// playwright.config.ts
import { defineConfig } from '@playwright/test';
import dotenv from 'dotenv';
import path from 'path';
// загружаем .env.local если есть, затем .env как запасной
dotenv.config({ path: path.resolve(__dirname, '.env.local') });
dotenv.config({ path: path.resolve(__dirname, '.env') });
export default defineConfig({
use: {
baseURL: process.env.BASE_URL || 'http://localhost:3000',
},
});.env.local добавь в .gitignore. .env коммить с безопасными дефолтами, без секретов. Каждый в команде создаёт свой .env.local с локальными учётными данными.
Несколько конфигов под окружения
Когда у окружений принципиально разные настройки, удобны отдельные конфиг-файлы:
playwright.config.ts # базовый конфиг, общие настройки
playwright.config.staging.ts # настройки для staging
playwright.config.prod.ts # продакшн (только smoke)// playwright.config.staging.ts
import { defineConfig } from '@playwright/test';
import baseConfig from './playwright.config';
export default defineConfig({
...baseConfig,
use: {
...baseConfig.use,
baseURL: 'https://staging.myapp.com',
video: 'on-first-retry',
},
retries: 2,
});Запуск:
npx playwright test --config=playwright.config.staging.tsСхема хорошо работает в CI-пайплайнах, где разные стадии требуют разного количества повторов, настроек видео или репортеров.
Переменные окружения в тестах
Не обращайся к переменным окружения напрямую из тестовых файлов. Это привязывает тестовую логику к инфраструктуре. Оборачивай в фикстуры:
// fixtures/env.ts
import { test as base } from '@playwright/test';
type EnvFixtures = {
testUser: { email: string; password: string };
apiToken: string;
};
export const test = base.extend<EnvFixtures>({
testUser: async ({}, use) => {
const email = process.env.TEST_USER_EMAIL;
const password = process.env.TEST_USER_PASSWORD;
if (!email || !password) {
throw new Error('TEST_USER_EMAIL and TEST_USER_PASSWORD must be set');
}
await use({ email, password });
},
apiToken: async ({}, use) => {
const token = process.env.API_TOKEN;
if (!token) throw new Error('API_TOKEN must be set');
await use(token);
},
});Тесты используют фикстуру, а не process.env напрямую:
import { test } from '../fixtures/env';
import { expect } from '@playwright/test';
test('user can log in', async ({ page, testUser }) => {
await page.goto('/login');
await page.getByLabel('Email').fill(testUser.email);
await page.getByLabel('Password').fill(testUser.password);
await page.getByRole('button', { name: 'Log in' }).click();
await expect(page).toHaveURL('/dashboard');
});Плюс очевидный: если переменная окружения не задана, получаешь понятную ошибку на уровне фикстуры вместо странного падения в середине теста.
Переменные окружения в CI/CD
В GitHub Actions секреты настраиваются в настройках репозитория, затем передаются в тесты:
# .github/workflows/tests.yml
jobs:
test:
runs-on: ubuntu-latest
env:
BASE_URL: ${{ vars.STAGING_URL }}
API_TOKEN: ${{ secrets.API_TOKEN }}
TEST_USER_EMAIL: ${{ secrets.TEST_USER_EMAIL }}
TEST_USER_PASSWORD: ${{ secrets.TEST_USER_PASSWORD }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright testvars (не secrets) используй для нечувствительных значений вроде staging URL: они видны в логах CI, что помогает при отладке. secrets используй для учётных данных, токенов и паролей.
Тест-данные под конкретные окружения
Некоторые тесты должны запускаться только в определённых окружениях. Используй теги и проверки окружения:
test('payment flow smoke test', {
tag: '@smoke',
annotation: { type: 'env', description: 'staging and production only' },
}, async ({ page }) => {
// пропускаем при локальной разработке — не нужен sandbox оплаты
test.skip(
process.env.BASE_URL?.includes('localhost') === true,
'Payment tests require staging or production environment'
);
// тело теста...
});Или через фикстуру которая определяет текущее окружение:
const currentEnv = process.env.BASE_URL?.includes('staging')
? 'staging'
: process.env.BASE_URL?.includes('localhost')
? 'local'
: 'production';Это избавляет от разбросанных по тест-файлам if (process.env.BASE_URL === '...').
Что в переменные, что в конфиг
| Настройка | Где должна быть |
|-----------|-----------------|
| Base URL | Переменная окружения |
| API-токены, пароли | Переменная окружения (секрет) |
| Тип браузера | Конфиг-файл |
| Количество повторов | Конфиг-файл (можно разное для окружений) |
| Таймауты | Конфиг-файл |
| Тест-данные | Фикстуры |
| Флаги фич для поведения тестов | Переменная окружения |
Правило простое: всё что отличается между окружениями идёт в переменную окружения. Всё что остаётся стабильной настройкой фреймворка идёт в конфиг-файл.
→ See also: Файл конфигурации Playwright: все опции, которые нужно знать | Переменные окружения в тестах Playwright: полное руководство | GitHub Actions для тестов Playwright: полная настройка (2026)