Перейти к основному содержимому

Параметризация тестов

Введение

Вы можете параметризовать тесты на уровне теста или на уровне проекта.

Параметризованные тесты

example.spec.ts
[
{ name: 'Alice', expected: 'Hello, Alice!' },
{ name: 'Bob', expected: 'Hello, Bob!' },
{ name: 'Charlie', expected: 'Hello, Charlie!' },
].forEach(({ name, expected }) => {
// Вы также можете сделать это с помощью test.describe() или с несколькими тестами, если имя теста уникально.
test(`testing with ${name}`, async ({ page }) => {
await page.goto(`https://example.com/greet?name=${name}`);
await expect(page.getByRole('heading')).toHaveText(expected);
});
});

Хуки до и после

В большинстве случаев вы должны размещать хуки beforeEach, beforeAll, afterEach и afterAll вне forEach, чтобы хуки выполнялись только один раз:

example.spec.ts
test.beforeEach(async ({ page }) => {
// ...
});

test.afterEach(async ({ page }) => {
// ...
});

[
{ name: 'Alice', expected: 'Hello, Alice!' },
{ name: 'Bob', expected: 'Hello, Bob!' },
{ name: 'Charlie', expected: 'Hello, Charlie!' },
].forEach(({ name, expected }) => {
test(`testing with ${name}`, async ({ page }) => {
await page.goto(`https://example.com/greet?name=${name}`);
await expect(page.getByRole('heading')).toHaveText(expected);
});
});

Если вы хотите иметь хуки для каждого теста, вы можете разместить их внутри describe(), чтобы они выполнялись для каждой итерации / каждого отдельного теста:

example.spec.ts
[
{ name: 'Alice', expected: 'Hello, Alice!' },
{ name: 'Bob', expected: 'Hello, Bob!' },
{ name: 'Charlie', expected: 'Hello, Charlie!' },
].forEach(({ name, expected }) => {
test.describe(() => {
test.beforeEach(async ({ page }) => {
await page.goto(`https://example.com/greet?name=${name}`);
});
test(`testing with ${expected}`, async ({ page }) => {
await expect(page.getByRole('heading')).toHaveText(expected);
});
});
});

Параметризованные проекты

Playwright Test поддерживает запуск нескольких тестовых проектов одновременно. В следующем примере мы запустим два проекта с разными опциями.

Мы объявляем опцию person и задаем значение в конфигурации. Первый проект запускается со значением Alice, а второй со значением Bob.

my-test.ts
import { test as base } from '@playwright/test';

export type TestOptions = {
person: string;
};

export const test = base.extend<TestOptions>({
// Определяем опцию и предоставляем значение по умолчанию.
// Мы можем позже переопределить его в конфигурации.
person: ['John', { option: true }],
});

Мы можем использовать эту опцию в тесте, аналогично фикстурам.

example.spec.ts
import { test } from './my-test';

test('test 1', async ({ page, person }) => {
await page.goto(`/index.html`);
await expect(page.locator('#node')).toContainText(person);
// ...
});

Теперь мы можем запускать тесты в нескольких конфигурациях, используя проекты.

playwright.config.ts
import { defineConfig } from '@playwright/test';
import type { TestOptions } from './my-test';

export default defineConfig<TestOptions>({
projects: [
{
name: 'alice',
use: { person: 'Alice' },
},
{
name: 'bob',
use: { person: 'Bob' },
},
]
});

Мы также можем использовать опцию в фикстуре. Узнайте больше о фикстурах.

my-test.ts
import { test as base } from '@playwright/test';

export type TestOptions = {
person: string;
};

export const test = base.extend<TestOptions>({
// Определяем опцию и предоставляем значение по умолчанию.
// Мы можем позже переопределить его в конфигурации.
person: ['John', { option: true }],

// Переопределяем стандартную фикстуру "page".
page: async ({ page, person }, use) => {
await page.goto('/chat');
// Мы используем параметр "person" как "name" для чата.
await page.getByLabel('User Name').fill(person);
await page.getByText('Enter chat room').click();
// Каждый тест получит "page", который уже имеет имя пользователя.
await use(page);
},
});
примечание

Поведение параметризованных проектов изменилось в версии 1.18. Узнайте больше.

Передача переменных окружения

Вы можете использовать переменные окружения для настройки тестов из командной строки.

Например, рассмотрим следующий тестовый файл, которому нужны имя пользователя и пароль. Обычно лучше не хранить ваши секреты в исходном коде, поэтому нам нужен способ передать секреты извне.

example.spec.ts
test(`example test`, async ({ page }) => {
// ...
await page.getByLabel('User Name').fill(process.env.USER_NAME);
await page.getByLabel('Password').fill(process.env.PASSWORD);
});

Вы можете запустить этот тест с вашим секретным именем пользователя и паролем, установленными в командной строке.

USER_NAME=me PASSWORD=secret npx playwright test

Аналогично, файл конфигурации также может считывать переменные окружения, переданные через командную строку.

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

export default defineConfig({
use: {
baseURL: process.env.STAGING === '1' ? 'http://staging.example.test/' : 'http://example.test/',
}
});

Теперь вы можете запускать тесты в промежуточной или производственной среде:

STAGING=1 npx playwright test

.env файлы

Чтобы упростить управление переменными окружения, рассмотрите возможность использования файлов .env. Вот пример, который использует пакет dotenv для считывания переменных окружения непосредственно в файле конфигурации.

playwright.config.ts
import { defineConfig } from '@playwright/test';
import dotenv from 'dotenv';
import path from 'path';

// Чтение из файла ".env".
dotenv.config({ path: path.resolve(__dirname, '.env') });

// Альтернативно, чтение из файла "../my.env".
dotenv.config({ path: path.resolve(__dirname, '..', 'my.env') });

export default defineConfig({
use: {
baseURL: process.env.STAGING === '1' ? 'http://staging.example.test/' : 'http://example.test/',
}
});

Теперь вы можете просто отредактировать файл .env, чтобы установить любые переменные, которые вы хотите.

# .env файл
STAGING=0
USER_NAME=me
PASSWORD=secret

Запустите тесты как обычно, ваши переменные окружения должны быть подхвачены.

npx playwright test

Создание тестов через CSV файл

Тест-раннер Playwright работает в Node.js, это означает, что вы можете напрямую читать файлы из файловой системы и разбирать их с помощью предпочитаемой библиотеки CSV.

Рассмотрим, например, этот CSV файл, в нашем примере input.csv:

"test_case","some_value","some_other_value"
"value 1","value 11","foobar1"
"value 2","value 22","foobar21"
"value 3","value 33","foobar321"
"value 4","value 44","foobar4321"

На основе этого мы сгенерируем несколько тестов, используя библиотеку csv-parse из NPM:

test.spec.ts
import fs from 'fs';
import path from 'path';
import { test } from '@playwright/test';
import { parse } from 'csv-parse/sync';

const records = parse(fs.readFileSync(path.join(__dirname, 'input.csv')), {
columns: true,
skip_empty_lines: true
});

for (const record of records) {
test(`foo: ${record.test_case}`, async ({ page }) => {
console.log(record.test_case, record.some_value, record.some_other_value);
});
}