vyvchy
    Теми розділу

    07 · Інструменти автоматизації

    Playwright: фікстури, хуки і конфігурація

    Зміст

    Найдорожчий рядок у тестовому проєкті — не і не перевірка, а той, що готує оточення: логін, , піднятий сервіс, чистий стан. Playwright віддає цю роботу двом різним механізмам — і хукам, — а над ними тримає третій рівень, конфігурацію, де вирішується, скільки разів усе це станеться і в яких варіантах. Поки в десять тестів, різниця між механізмами не видна. На двохсотому тесті вона визначає, чи прогін вкладається в хвилини, чи розтягується на десятки, і чи падає він у паралелі.

    Ця глава — про механіку саме цих трьох речей у Playwright: що тест отримує безкоштовно, як оголосити своє, чим worker відрізняється від test, і що насправді робить playwright.config.ts. Два питання — «фікстура чи beforeEach» і «як ти ганяєш ті самі тести на трьох браузерах» — миттєво показують, чи людина налаштовувала фреймворк, чи копіювала приклади. Концептуальний бік — навіщо взагалі (test runner), фікстури й хуки — канон розділу «Автоматизація»; тут — механіка конкретного інструмента.

    Вбудовані фікстури: оточення, яке тест не будує

    Фікстура (fixture) у Playwright — це іменований шматок оточення тесту. Джерельне означення звучить так: фікстури встановлюють оточення для кожного тесту, даючи тесту все, що йому потрібно, і нічого зайвого, і вони ізольовані між тестами. ISTQB формулює те саме ширше: фікстура — це те, що має бути доступним, аби тест міг виконатися, і вона прямо повʼязана з повторюваністю й атомарністю тесту.

    Тест не запускає браузер і не створює профіль. Він просто називає в аргументах те, що йому потрібно:

    import { test, expect } from '@playwright/test';
    
    test('кошик порожній у нового користувача', async ({ page }) => {
      await page.goto('/cart');
      await expect(page.getByText('Кошик порожній')).toBeVisible();
    });

    Дужки { page } тут не магія, а замовлення: ранер читає імʼя параметра, піднімає фікстуру page і віддає її в тестову функцію. Три вбудовані фікстури варто знати назубок:

    ФікстураЩо цеХто нею володіє
    pageізольована сторінка цього прогону тестутест
    contextізольований контекст браузера (browser context), якому належить pageтест
    browserсам браузер, спільний між тестами заради економії ресурсівворкер (worker)

    Уся економіка ізоляції — у цій асиметрії: браузер спільний, а контекст і сторінка — ні. «Спільний» тут означає «на воркер-процес, який виконує тести», а не «один на весь прогін»: кожен стартує власний браузер. Кожен тест дістає свіжий контекст, еквівалентний новому профілю браузера, але не платить за запуск процесу. Дока прямо називає ізоляцію причиною відтворюваності й захисту від каскадних падінь — тобто чистий стан між тестами не «прибирають», його дають новим контекстом.

    Друга властивість, яку легко проґавити: фікстури ліниві. Ранер створює page і context, лише якщо тест назвав їх у своїх аргументах, і закриває їх сам. Для порівняння: у бібліотечному режимі, без ранера, ієрархію browser → context → page вибудовують вручну й закривають теж вручну — саме цю різницю розбирає глава Playwright: архітектура, браузери і контексти.

    Третя властивість — не про швидкість, а про структуру: фікстури дають групувати тести за змістом, а не за спільною підготовкою. Це прямий аргумент проти файлів, зліплених за принципом «тут усе, що потребує залогіненого адміна».

    test.extend і скоупи: test проти worker

    Власна фікстура оголошується розширенням базового test через test.extend:

    import { test as base } from '@playwright/test';
    
    type Fixtures = { cart: Cart };
    
    export const test = base.extend<Fixtures>({
      cart: async ({ page }, use) => {
        const cart = await createCart(page);  // setup
        await use(cart);                      // тут виконується тіло тесту
        await cart.remove();                  // teardown
      },
    });

    Усе до use — підготовка, усе після — , яке ранер викличе сам. Фікстура може залежати від іншої (cart просить page), і порядок вибудовує ранер, а не автор.

    Скоуп задається другим параметром типу і кортежним синтаксисом:

    export const test = base.extend<{}, { apiToken: string }>({
      apiToken: [async ({}, use) => {
        const token = await issueToken();
        await use(token);
      }, { scope: 'worker' }],
    });

    Кортеж [fn, { scope: 'worker' }] — не стилістика, а єдиний спосіб сказати ранеру, що фікстуру треба поставити раз на воркер-процес. Різниця в житті двох скоупів проста: тестова фікстура прибирається після кожного тесту, воркерна — лише коли завершується сам воркер.

    Старт воркера

    worker-фікстури: setup

    test-фікстури тесту 1

    Тіло тесту 1

    test-фікстури: teardown

    test-фікстури тесту 2

    Тіло тесту 2

    test-фікстури: teardown

    Воркер завершується

    worker-фікстури: teardown

    Старт воркера

    worker-фікстури: setup

    test-фікстури тесту 1

    Тіло тесту 1

    test-фікстури: teardown

    test-фікстури тесту 2

    Тіло тесту 2

    test-фікстури: teardown

    Воркер завершується

    worker-фікстури: teardown

    З цієї схеми випливають три речі.

    Воркер перевикористовується не завжди. Ранер віддає одному воркеру стільки файлів, скільки може, — але тільки поки воркерні фікстури збігаються, тобто оточення ідентичне. Розвів файли різними значеннями воркерної фікстури — і замість отримав старт нового воркера з усією його ціною.

    У воркерної фікстури власний , рівний дефолтному таймауту тесту. Тобто «підняти сервіс» не змагається за секунди з тілом тесту, але й безмежного часу не має. Самі рівні таймаутів розбирає глава Playwright: перевірки і автоочікування.

    Скоуп — це компроміс, а не оптимізація. Воркерний скоуп економить час на дорогій підготовці, але повертає в сюїту спільний стан: усе, що тест змінює, стає видимим наступним тестам того самого воркера. Класика вибору звучить так: усе, що тести лише читають (зʼєднання, піднятий сервер, службовий токен), — кандидат на worker; усе, що тест мутує, лишається на test.

    Фікстури проти хуків: різниця не в синтаксисі

    Хук тесту (test hook) виконується завжди. Фікстура — лише коли її попросили. Це вся різниця, і з неї випливає решта.

    Дока називає три властивості фікстур, яких у хуків немає:

    • інкапсуляція — setup і teardown лежать в одному місці. Звідси готовий критерій рефакторингу: якщо after-хук прибирає те, що створив before-хук, це кандидат на фікстуру;
    • перевикористання між файлами — оголосив раз, використовуєш у всіх тестах;
    • on-demand — піднімається лише те, що тест справді просить, і нічого зайвого.

    Хуки при цьому не зло. Офіційна дока прямо називає їх легітимним способом уникнути повторення й додає, що самі по собі вони ізоляції не порушують, бо жоден тест не залежить від іншого. Механіка хуків спільна для ранерів: beforeEach/afterEach — на кожен тест, beforeAll/afterAll — раз на файл; хуки верхнього рівня діють на всі тести файлу, а оголошені в describe — лише на тести свого блоку; порядок жорсткий: зовнішній beforeEach виконується раніше за вкладений. Хуки можуть бути асинхронними — власне, beforeAll/afterAll і існують для підготовки «один раз на початку файлу», яку через асинхронність не зробиш інлайн.

    А тепер пастка Playwright, якої в «класичній» моделі немає. У повністю паралельному режимі «раз на файл» перестає означати «раз». Тести того самого файлу йдуть в окремих воркерах, спільного стану й глобальних змінних між ними немає, і кожен тест виконує всі релевантні хуки сам для себе — включно з beforeAll і afterAll.

    Виглядає це буденно: beforeAll створює одне замовлення, три тести його читають. У паралелі створиться три замовлення, кожне у своєму воркері, — і якщо код на це не розрахований (унікальний email, номер, зайнятий слот), сюїта червона рівно там, де «економили».

    Що готуємоКуди це кладуть
    дороге зʼєднання чи сервіс, який тести лише читаютьворкерна фікстура
    дані, які тест змінюєтестова фікстура
    повторювана дія без результату, що передається в тестхук
    підготовка, потрібна не всім тестам файлуфікстура (бо on-demand)

    Діагностичний рефлекс, який радить дока Jest, вартий того, щоб довести до автоматизму: перше питання при падінні — чи падає тест, коли він єдиний у прогоні. Падає сам — проблема в тесті. Падає лише в наборі — проблема в спільному стані, тобто в хуку або в .

    playwright.config: два рівні, які плутають

    Конфіг ділиться на два рівні, і дока застерігає про це прямо: опції самого ранера живуть на верхньому рівні, а опції оточення тесту — в секції use, і окремою приміткою дока просить не класти перші в другу. Тобто це не косметика, а розподіл повноважень.

    import { defineConfig } from '@playwright/test';
    
    export default defineConfig({
      testDir: './tests',                    // опція ранера
      fullyParallel: true,                   // опція ранера
      forbidOnly: !!process.env.CI,          // опція ранера
      retries: process.env.CI ? 2 : 0,       // опція ранера
      use: {                                 // оточення тесту
        baseURL: process.env.BASE_URL ?? 'http://localhost:3000',
        trace: 'on-first-retry',
      },
    });

    Мнемоніка проста: retries — про те, як ранер поводиться з тестом; trace і baseURL — про те, в якому оточенні тест живе. ISTQB описує той самий шов концептуально: узагальнена архітектура автоматизації відокремлює визначення тесту від системи під тестом і від інструментів, і конфіг — саме те місце, де ця межа матеріалізується.

    baseURL — найдешевша інвестиція в : відносний аргумент page.goto('/cart') резолвиться відносно нього, тож середовище перемикається змінною оточення, а не правками в тестах. Резолвінг відносних адрес як явище розібраний у главі URL і кодування.

    Базовий конфіг із доки навмисно розводить локальний запуск і CI: лише в CI, forbidOnly в CI (щоб забутий test.only завалив , а не тихо звузив прогін до одного тесту), на першому ретраї впалого тесту, локальний dev-сервер піднімається перед прогоном. Політику ретраїв як таку — коли вони виявляють , а коли маскують — розбирає глава Боротьба з флаком засобами інструмента.

    Варто знати, що модель «конфіг = опції» не єдина. У CodeceptJS конфіг несе ще й роль реєстру : include перелічує обʼєкти, які потім інжектяться в сценарій за іменем, а хелпер задає рушій виконання (Playwright, WebDriver, Puppeteer, Appium) — тож той самий набір сценаріїв перемикається між рушіями через конфіг. Деталі — у главі CodeceptJS: актор, хелпери і сценарний стиль.

    Проєкти: матриця конфігурацій замість трьох пайплайнів

    Проєкт (project) у конфігурації ранера — це логічна група тестів, що виконуються з однаковою конфігурацією. Не тека, не сюїта і не «підпроєкт у таск-трекері»: той самий файл може належати кільком проєктам і прогнатися в кожному по-своєму. Приклад із самої доки — той самий тест у залогіненому й незалогіненому стані.

    Браузери — лише найвідоміше застосування. Проєктами розкладають і різні таймаути, і різні ретраї, і різні середовища (staging проти прода), і поділ за пакетом чи функціональністю. Кросбраузерний прогін при цьому описується списком проєктів у конфізі, а не трьома командами запуску чи трьома .

    projects: [
      { name: 'setup', testMatch: /.*\.setup\.ts/, teardown: 'cleanup' },
      { name: 'cleanup', testMatch: /.*\.cleanup\.ts/ },
      {
        name: 'chromium',
        use: { browserName: 'chromium', storageState: 'playwright/.auth/user.json' },
        dependencies: ['setup'],
      },
      {
        name: 'webkit',
        use: { browserName: 'webkit', storageState: 'playwright/.auth/user.json' },
        dependencies: ['setup'],
      },
    ],

    Кожен проєкт задає власну секцію use — звідси й «той самий тест, інший браузер» або «той самий тест, інший базовий URL». За замовчуванням ранер виконує всі проєкти; звузити до одного — --project, тобто рішення прогону, а не конфіга.

    dependencies — це список проєктів, які мають відпрацювати перед тестами іншого проєкту. Саме так робиться «один раз перед усім»: логін, даних, прогрів кешу. Три деталі відрізняють того, хто це справді налаштовував:

    • setup-тести видно в репортері, і трейс на них теж записується — підготовка дебажиться тими самими інструментами, що й тести;
    • кілька залежностей виконуються паралельно, а якщо тести залежності впали, залежні тести не запускаються взагалі — вони не «червоні», бо жодного разу не виконалися;
    • прибирання чіпляється до setup-проєкту окремою властивістю teardown і відпрацьовує після всіх залежних проєктів, а не після кожного.

    Проєкт setup
    логін, стан

    Проєкт chromium

    Проєкт webkit

    teardown: cleanup

    Проєкт setup
    логін, стан

    Проєкт chromium

    Проєкт webkit

    teardown: cleanup

    І пастка, яка спершу виглядає як баг ранера: будь-яка фільтрація — --grep, --shard, шлях у командному рядку, test.only — вибирає основні тести, а тести залежностей підтягуються самі. Тому шард на CI не лишається без логіну, хоч у його вибірці setup-тестів немає. Свідомо відрубати це можна прапорцем --no-deps — і тоді запустяться лише вибрані проєкти.

    Механіку (storage state) розбирає глава Playwright: автентифікація і повторне використання стану, а воркери й між машинами — Паралельний запуск: workers, шардінг, браузерні ферми.

    Анотації і теги: намір, а не «вимкнути тест»

    Playwright підтримує теги й анотації, які показуються у звіті. Вбудованих анотацій чотири, і це чотири різні наміри — плутати їх дорого:

    АнотаціяТест запускаєтьсяСенс
    test.skip()нінезастосовно в цій конфігурації
    test.fixme()ніпадає чи крешить, запускати не варто
    test.fail()такмусить упасти; якщо пройде — ранер поскаржиться
    test.slow()такповільний: таймаут тесту втричі більший

    Пару fail проти fixme плутають, бо назви обидві звучать як «тест не працює». Насправді fail тест запускає й вимагає падіння: зелений результат стає помилкою. Це точний механізм для ситуації «баг є, і я хочу дізнатися в той день, коли його виправлять». fixme не запускає взагалі — дока радить його саме тоді, коли тест повільний або крешить.

    Анотації можуть бути умовними: застосовуються, коли умова істинна, і можуть залежати від фікстур. На одному тесті їх може бути кілька, у різних конфігураціях. Тому «пропустити на WebKit» — це не if у тілі тесту:

    test('вибір файлу', async ({ page, browserName }) => {
      test.skip(browserName === 'webkit', 'діалог не піднімається в цій збірці');
      // ...
    });

    Теги, як і анотації, показуються у звіті, а відбір за ними робиться тим самим фільтром, що й за назвою: позначив тест — і відбираєш його через --grep; зворотний відбір, «усе, крім позначеного», — --grep-invert. Звідси й типова розкладка прогонів: @smoke на кожен PR, повна вночі.

    Тут же варто розвести інструмент і теорію, бо на цьому ловлять. «Статус» у звіті ранера — не шкала ISTQB. Силабус CTFL 4.0 подає passed/failed як міру прогресу, а ширшої шкали виконання — blocked, skipped — не дає ні він, ні , який означує результат тесту просто як статус виконання тесту. Тобто test.skip — анотація конкретного ранера з власною семантикою, а не нормативний «статус кейсу»: у TMS «skipped» може означати одне, у звіті Playwright — інше, і сильна відповідь на співбесіді цю різницю називає, а не змішує.

    Параметризація: рівень тесту і рівень проєкту

    Дока розводить два рівні прямо: параметризувати можна на рівні тесту або на рівні проєкту. Плутанина між ними — джерело і дублювання коду, і хибних очікувань від звіту.

    Рівень тесту — набір даних усередині файлу: , межі одного поля. Механіка буденна — звичайний обхід масиву, а єдина формальна вимога — унікальна назва тесту.

    const cases = [
      { input: '', error: 'Порожнє поле' },
      { input: 'a@', error: 'Некоректна адреса' },
    ];
    
    for (const item of cases) {
      test(`валідація email: ${item.input || 'порожньо'}`, async ({ page }) => {
        await page.goto('/signup');
        await page.getByLabel('Email').fill(item.input);
        await expect(page.getByRole('alert')).toHaveText(item.error);
      });
    }

    Пастка тут одна, зате постійна — розміщення хуків. Дока рекомендує ставити beforeEach, beforeAll, afterEach і afterAll поза циклом, щоб вони виконалися один раз; а якщо хуки потрібні на кожен набір, їх кладуть усередину describe(), і тоді вони спрацюють на кожній ітерації. Це і є найчастіша причина скарги «у другому кейсі дані вже не ті».

    Рівень проєкту — той самий тест на різних конфігураціях. Параметр оголошується як опція з дефолтом і читається в тесті так само, як фікстура:

    // fixtures.ts
    export const test = base.extend<{ person: string }>({
      person: ['John', { option: true }],
    });
    
    // playwright.config.ts
    projects: [
      { name: 'alice', use: { person: 'Alice' } },
      { name: 'bob', use: { person: 'Bob' } },
    ],

    Перший проєкт прожене набір зі значенням Alice, другий — з Bob. Окремого data provider у Playwright немає, і це не бідність API: опція проєкту — це та сама фікстура, лише зі значенням із конфігу, і дока прямо каже, що в тесті вона читається так само, як фікстура. Комбінації конфігурацій живуть саме на цьому рівні; як їх добирати, щоб не отримати комбінаторний вибух, — тема розділу «Тест-дизайн».

    Типові помилки

    • Виглядає як «фікстура не спрацювала», а насправді тест її не просив. Фікстури on-demand: не назвав у аргументах — ранер її не піднімав. У хука така поведінка неможлива, тому інтуїція «підготовка ж є в файлі» тут підводить.
    • Виглядає як «воркерний скоуп зекономив час», а насправді ранер підняв новий воркер. Один воркер бере наступні файли, лише поки воркерні фікстури збігаються. Різні значення воркерної фікстури = різні оточення = нові воркери з усією ціною старту.
    • Виглядає як «прибирання є», а насправді teardown не знає, що встигло створитися. after-хук, який прибирає створене before-хуком, — це рознесені по файлу половинки одного механізму; дока прямо каже, що це кандидат на фікстуру, де setup і teardown лежать разом.
    • Виглядає як «проєкт — це тека з тестами», а насправді це конфігурація. Той самий файл може прогнатися в пʼятьох проєктах, тому фраза «упав тест логіну» без назви проєкту — не діагноз: у Chromium і WebKit це два різні результати.
    • Виглядає як «залежність упала, тести червоні», а насправді вони не виконувалися. Падіння setup-проєкту не робить залежні тести failed — воно їх не запускає. Шукати їхній результат у звіті марно, дивитись треба на setup.
    • Виглядає як «шард на CI побіжить без логіну», а насправді залежності підтягуються самі. --grep, --shard і test.only вибирають лише основні тести, а тести залежностей ранер додає сам; свідомо відрубати їх можна тільки прапорцем --no-deps.
    • Виглядає як «дані в другому кейсі не ті», а насправді хук стоїть не там. Хук поза циклом параметризації виконується один раз на всі набори — і другий набір бачить залишки першого.

    Підсумок

    • Фікстура дає тесту оточення на вимогу: page і context ізольовані на тест, а browser спільний у межах воркера — саме тому ізоляція в Playwright майже безкоштовна.
    • Хук виконується завжди, фікстура — лише коли її попросили; звідси три властивості фікстур, яких у хуків немає: інкапсуляція setup і teardown, перевикористання між файлами, on-demand.
    • Скоуп worker економить дорогу підготовку, але повертає спільний стан, а воркер перевикористовується лише поки воркерні фікстури збігаються.
    • У повністю паралельному режимі «раз на файл» не означає «раз»: кожен тест виконує beforeAll/afterAll сам для себе, і глобальних змінних між воркерами немає.
    • Конфіг має два рівні (опції ранера проти секції use), а проєкти — це матриця конфігурацій із залежностями, де setup-проєкт підтягується навіть у відфільтрований прогін.

    Можливі питання

    • «Що таке фікстура і чим вона краща за beforeEach Сильна відповідь: setup і teardown в одному місці, перевикористання між файлами, on-demand, композиція через залежності й керований скоуп. Інтервʼюер слухає, чи звучить слово «лише коли попросили».
    • «Чим відрізняються скоупи test і worker? Що покладеш у кожен?» Перевіряють розуміння ціни ізоляції: читаємо — worker, мутуємо — test. Плюс бонус: назвати умову перевикористання воркера.
    • «Як ти ганяєш ті самі тести на трьох браузерах?» Правильна відповідь — матриця проєктів у конфізі, а не три команди й не три пайплайни. Відповідь «три джоби в CI» одразу показує, що проєктів людина не налаштовувала.
    • «Як зробити логін один раз на весь прогін?» Очікують setup-проєкт із dependencies, а не beforeAll у кожному файлі. Хороший кандидат додає, що падіння setup не робить тести червоними — воно їх не запускає.
    • «У чому різниця між test.skip, test.fixme і test.fail Дивляться, чи розрізняєш «не запускати» і «запустити й вимагати падіння», бо це різні інструменти для різних станів .
    • «Тести падають у паралелі, а по одному зелені. З чого почнеш?» Місток до ізоляції: спільний стан у хуку чи воркерній фікстурі, спільний акаунт, спільні дані. Питання «а тест падає, коли він єдиний у прогоні?» тут — правильний перший крок.

    Джерела

    Вбудовані фікстури: оточення, яке тест не будує

    • Playwright — Test fixtures — означення фікстури, ізольованість між тестами, лінивість, і те, що фікстури групують тести за змістом, а не за спільною підготовкою.
    • ISTQB® Certified Tester Advanced Level Test Automation Engineering (CTAL-TAE) v2.0 — §4.2: фікстура — те, що має бути доступним, аби тест міг виконатися; фікстури дають контроль над оточенням і даними й повʼязані з повторюваністю й атомарністю.
    • xUnit Test Patterns — Fresh Fixture — фікстура означена як стан тестового оточення перед тестом, а вибір «будувати її щоразу заново чи перевикористовувати» названо ключовим рішенням автоматизації.
    • Playwright — Library — ранер віддає тесту вже ізольовані page і context як вбудовані фікстури й створює їх ліниво; у бібліотеці ту саму ієрархію будують і закривають вручну.
    • Playwright — головна сторінка — кожен тест дістає свіжий контекст, еквівалентний новому профілю браузера, з ізоляцією майже без накладних витрат.
    • Playwright — Authentication — ізоляція контекстів названа причиною відтворюваності й захисту від каскадних падінь.
    • Playwright — Isolation (browser contexts) — контекст як механізм ізоляції та багатокористувацьких сценаріїв.
    • Playwright — Browsers — які рушії й брендові збірки водить інструмент, тобто чим є той спільний browser.
    • Playwright — Parallelism — воркер є окремим процесом ОС, який стартує власний браузер: звідси «спільний на воркер», а не «спільний на прогін».

    test.extend і скоупи: test проти worker

    • Playwright — Test fixturestest.extend, кортежний синтаксис scope: 'worker', прибирання тестової фікстури після кожного тесту й воркерної — при завершенні воркера, перевикористання воркера лише поки воркерні фікстури збігаються, окремий таймаут воркерної фікстури.
    • xUnit Test Patterns — Fresh Fixture — «щоразу заново проти перевикористання» як ключове рішення: це і є вибір між test і worker.
    • ISTQB® Certified Tester Advanced Level Test Automation Engineering (CTAL-TAE) v2.0 — §4.2: фікстури дають контроль над оточенням і даними, а й постумови задаються явно.

    Фікстури проти хуків: різниця не в синтаксисі

    • Playwright — Test fixtures — три властивості, яких немає в хуків: інкапсуляція setup і teardown в одному місці, перевикористання між файлами, on-demand.
    • Jest — Setup and Teardown — чотири хуки й різниця «на кожен тест проти раз на файл», скоуп describe, порядок вкладених beforeEach, асинхронні хуки і діагностичне питання «чи падає тест сам».
    • Playwright — Best Practices — хуки названо легітимним способом уникнути повторення, і самі по собі вони ізоляції не порушують.
    • Playwright — Parallelism — у повністю паралельному режимі тести не можуть ділити стан чи глобальні змінні, а всі релевантні хуки, включно з beforeAll і afterAll, кожен тест виконує сам для себе.
    • ISTQB® Certified Tester Advanced Level Test Automation Engineering (CTAL-TAE) v2.0 — §4.2: явні передумови й постумови як зміст фікстури.
    • xUnit Test Patterns — Fresh Fixture — свіжа фікстура проти перевикористаної як рамка для вибору «хук чи фікстура».

    playwright.config: два рівні, які плутають

    • Playwright — Test configuration — два рівні конфігу з прямим застереженням не класти опції ранера в use, baseURL для відносних page.goto(), і набір дефолтів доки для CI: ретраї лише в CI, forbidOnly, трейс на ретраї, підняття dev-сервера.
    • CodeceptJS — Configuration — інша модель конфігу: реєстр впровадження залежностей через include і хелпер, що задає рушій виконання.
    • ISTQB® Certified Tester Advanced Level Test Automation Engineering (CTAL-TAE) v2.0 — §3.1.1, §3.1.3: gTAA відокремлює визначення тесту від системи під тестом і від інструментів; шари фреймворку рекомендовано тримати низькими.

    Проєкти: матриця конфігурацій замість трьох пайплайнів

    • Playwright — Projects — означення проєкту, розкладка за таймаутами, ретраями й середовищами, дефолт «усі проєкти» проти --project, залежності та їхня паралельність, teardown на setup-проєкті, і те, що фільтрація підтягує залежності, а --no-deps їх вимикає.
    • Playwright — Browsers — кросбраузерна матриця як список проєктів: рушії Chromium/WebKit/Firefox і брендові канали.
    • Playwright — Test configuration — межа рівнів конфігу, на якій тримається власна секція use кожного проєкту.

    Анотації і теги: намір, а не «вимкнути тест»

    • Playwright — Annotations and tags — теги й анотації показуються у звіті; семантика skip/fail/fixme/slow, умовні анотації, залежні від фікстур, і відбір через --grep та --grep-invert.
    • ISTQB Certified Tester Foundation Level Syllabus v4.0 (копія astqb.org) — §1.4.1: виконання тестів, порівняння фактичних результатів з очікуваними й логування; §5.3.1: passed/failed як метрика прогресу, ширшої шкали статусів силабус не дає.
    • ISTQB Glossary — канонічні означення прогону й результату тесту: результат тесту означено як статус виконання тесту, самої шкали значень словник не нормує.

    Параметризація: рівень тесту і рівень проєкту

    • Playwright — Parameterize tests — два рівні параметризації, вимога унікальної назви тесту, розміщення хуків поза циклом проти хуків усередині describe(), і опція проєкту (option: true), яка читається в тесті як фікстура.

    Типові помилки

    • Playwright — Test fixtures — on-demand як причина «фікстура не піднялась», умова перевикористання воркера, і критерій «after прибирає створене before» → фікстура.
    • Playwright — Projects — проєкт як конфігурація, а не тека; поведінка при падінні залежності; фільтрація, що тягне залежності, і --no-deps.
    • Playwright — Parameterize tests — хуки поза циклом виконуються один раз, усередині describe() — на кожну ітерацію.
    • Playwright — Browsers — той самий тест у різних рушіях дає різні результати, тож назва проєкту є частиною діагнозу.
    • Playwright — Test configuration — два рівні конфігу: опції ранера живуть на верхньому рівні, і дока прямо застерігає не класти їх у use.
    • ISTQB® Certified Tester Advanced Level Test Automation Engineering (CTAL-TAE) v2.0 — §4.2: явні передумови й постумови як умова повторюваності — те, що ламається в кожній із цих помилок.
    • xUnit Test Patterns — Fresh Fixture — ціна перевикористаної фікстури, з якої й ростуть помилки скоупу.

    Можливі питання

    • Playwright — Test fixtures — три властивості фікстур проти хуків, скоупи test і worker, умова перевикористання воркера.
    • Playwright — Projects — матриця проєктів замість трьох пайплайнів, dependencies для «логін один раз» і поведінка при падінні setup-проєкту.
    • Playwright — Browsers — рушії, з яких складається кросбраузерна матриця.
    • Playwright — Annotations and tags — семантика skip/fixme/fail, на якій тримається питання про різницю.
    • Playwright — Parallelism — у паралельному режимі тести не ділять стан і глобальні змінні, а хуки кожен тест виконує сам для себе.
    • Jest — Setup and Teardown — «чи падає тест, коли він єдиний у прогоні» як перше діагностичне питання.
    • xUnit Test Patterns — Fresh Fixture — «щоразу заново проти перевикористання» як рамка відповіді про скоупи.

    Пояснення

    «Поясни» працює з власним API-ключем Anthropic: запит іде з вашого браузера прямо до Anthropic.

    Свій API-ключ (BYOK)

    Вставте власний ключ Anthropic — пояснення працюватиме на реальній моделі. Ключ зберігається лише у вашому браузері (localStorage), нікуди не надсилається, крім api.anthropic.com, і не логується.