Playwright - основы тестирования

Для начала почитаем очень полезную вводную »

Установка

npm i npx
npm install @playwright/test
npx playwright install

Конфигурирование

Создайте файл playwright.config.ts с содержимым:

import {devices, PlaywrightTestConfig} from '@playwright/test';

const config: PlaywrightTestConfig = {
    // уберите 000 и получишь секунды:
    timeout: 3000000,
    use: {
        // false - показывать браузер:
        headless: false,
        // разрешение браузера:
        viewport: { width: 1280, height: 720 },
    },
};
export default config;

Использование

Создаем файл dir/my-test.spec.ts в котором пишем код теста и запускаем: npx playwright test dir/my-test.spec.ts

Однако, для удобства написания тестов мы можем использовать следующие env-переменные со значениями:

 PWDEBUG=1PWDEBUG=consolePWDEBUG не указан
отладочная панель+--
бесконечный таймаут по умолчанию +--
браузер отображается++-
console.log(...) пишет в stdout+++

Пример: PWDEBUG=1 npx playwright test dir/my-test.spec.ts

Важно: если указать переменную DEBUG=pw:api то в stdout будет писаться отладочная информация

Функции задержки (sleep):

function delay(ms: number) {
    return new Promise( resolve => setTimeout(resolve, ms) );
}
function delaySeconds(seconds: number) {
    return new Promise( resolve => setTimeout(resolve, seconds * 1000) );
}

Переиспользуемые переменные:

let i = 0;
let n = 0;
let elements = null;
let count = null;

Клик по элементам:

await page.click('[data-test="have-account"]');
await page.locator('[data-test="have-account"]').click(); // тоже самое

Клик по элементам с указанным таймаутом в 10 секунд (с перехватом TimeOut эксепшена):

await page.click('[data-test="stories-player-continue"]', {timeout: 10000}).catch((reason) => {
    console.log('I waited 10 seconds');
});

Клик по первому элементу:

await page.locator('[data-test="story-start-button"]').first().click();

Нахождение нескольких элементов:

elements = await page.locator('[data-test="stories-choice"]');
count = await elements.count();

Обработка найденных элементов:

if (count > 0) {
    for (n = 0; n < count; n++) {
        await elements.nth(i).click({timeout: 1000}).catch((reason) => {
            console.log('I waited 1 second');
        });
    }
}

Важно: если элементы не были найдены, то возможно стоит подождать вызвав delaySeconds(seconds);

Нахождение текста для элемента:

text = await page.locator('[data-test="my-button"]').first().textContent();
if (text === 'Текст') {
    // ...
}

Нахождение значения атрибута у элемента:

text = await page.locator('[data-test="my"]').getAttribute('my-attribute', {timeout: 1000}).catch((reason) => {
    console.log('I waited 1 second');
});
// тоже самое:
text = page.locator('[data-test="my"]').evaluate(node => node.getAttribute('my-attribute'), {timeout: 1000}).catch((reason) => {
    console.log('I waited 1 second');
})

Заполнение INPUT-а:

await page.fill('[data-test="password-input"]', 'pa$$');

Функция определения включен элемент или нет:

async function isEnabled(locator:Locator, timeout:number = 100) : Promise<boolean | void> {
    console.log('isEnabled start:');
    let result = await locator.isEnabled({timeout: timeout}).catch((reason) => {
        console.log('isEnabled timeout');
    });
    console.log('isEnabled end:');
    return result;
}

и два варианта ее применения (отличие в указании времени ожидания):

if (true === await isEnabled(page.locator('[data-test="my-button"]'))) {
    continue;
}
if (true === await isEnabled(page.locator('[data-test="my-button"]'), 1000)) {
    break;
}

Примеры того, как работают селекторы:

  1. selectors
  2. scraping
  3. class-selectors
  4. class-locator
  5. class-page

Как обрабатывать найденные элементы словно работаем с обычными JS-элементами:

  1. locator-element-handle
  2. class-elementhandle

Таймауты:

  1. actionability
  2. test-timeouts

Альтернативный подход

Оказывается, можно писать не только тесты, но и автоматизировать какие-нибудь процессы, давайте рассмотрим такой пример.

Установка

cd /var/www/jb/app/playwright &&
wget https://nodejs.org/download/release/latest-v20.x/node-v20.17.0-linux-x64.tar.gz &&
tar -xzf 'node-v20.17.0-linux-x64.tar.gz' &&
unlink node-v20.17.0-linux-x64.tar.gz &&
mv node-v20.17.0-linux-x64 nodejs &&
sudo ln -s /var/www/jb/app/playwright/nodejs/bin/node /usr/bin/node

Playwright only works with the bundled Chromium, Firefox or WebKit, установим их:

node /var/www/jb/app/playwright/nodejs/bin/npx playwright install

Устанавливать пакеты тестирования нужно, только если собираемся писать тесты:

node ./nodejs/bin/npm install --save-dev @playwright/test
node /var/www/jb/app/playwright/nodejs/bin/npx playwright test my-test.spec.ts -x

Настройка

Создавать файл playwright.config.ts нужно, только если собираемся писать тесты:

import {devices, PlaywrightTestConfig, defineConfig} from '@playwright/test';

export default defineConfig({
    // убери 000 и получишь секунды
    timeout: 86000000,
    use: {
        headless: false,
        viewport: { width: 1280, height: 720 },
        launchOptions: {
            executablePath: '/usr/bin/google-chrome',
        }
    },
    //  --project=GoogleChromeX
    // projects: [
    //     {
    //         name: 'GoogleChromeX',
    //         use: { ...devices['Desktop Chrome'], channel: 'chrome' }, // or 'chrome-beta'
    //     },
    // ],
});

потому что в примере ниже, файл playwright.config.ts не участвует.

Пример скрипта

Создаем файл pw.js

const { chromium } = require("playwright"); // ^1.38.0

let browser;
(async () => {
    const userDataDir = "test";
    browser = await chromium.launchPersistentContext(userDataDir, {headless: false});
    chromium.con
    const page = await browser.newPage();
    await page.goto("https://accounts.google.com/");
    console.log(await page.locator("h1").textContent());
})()
    .catch(err => console.error(err))
    .finally(() => browser?.close());

Запускаем файл так:

node pw

Интересное

1. В интернете пишут, что можно использовать свои уже имеющиеся настройки браузера, например:

# login with firefox ...
ff_page.context.storage_state("/path/to/file")
chrome = playwright.chromium.launch()
chrome.new_context(storage_state="/path/to/file")

2. Можно использовать атрибуты влияюще на поведение браузера: 1 - 2 - 3

3. Команда playwright обычный браузер называет branded Google Chrome

4. В плейврайет есть аналог xdebug

5. Playwright может записывать видео

Чем не устраивает

При всех преимуществах Playwright меня не устраивает по причинам:

  1. неудобная документация написанная разработчиками для самих себя, нежели для други неопытных js-прогеров
  2. в связи с пунктов выше, слишком много времени уходит на написание тестов и отладку

11.09.2021 07:08