Лайвкодинг для AQA
Зміст
Лайвкодинг (live coding) — це коли на технічній співбесіді тебе просять писати код прямо зараз, з інтерв'юером за плечем: розв'язати невелику задачку, накидати автотест на живу сторінку або розібрати чужий код. Для більшості кандидатів, що переходять з мануального тестування в автоматизацію, це найстрашніший етап — не тому, що задачі складні, а тому, що доводиться думати вголос під наглядом, і будь-яка пауза здається провалом.
Головне непорозуміння, через яке валяться навіть сильні кандидати: лайвкодинг перевіряє не те, чи напишеш ти ідеальний код без єдиної помилки. Він перевіряє, як ти думаєш — чи вмієш розкласти задачу, поставити уточнювальні питання, згадати крайові випадки, зреагувати на підказку. Робочий код — приємний бонус, але інтерв'юер бачив сотні розв'язків FizzBuzz; його цікавить процес, а не відповідь. Ця глава — про формати, критерії оцінки й тактику, а не про самі задачі: банк алгоритмічних задач із розв'язками живе в розділі «JavaScript/TypeScript для AQA» (глава про live coding), а розбір «протестуй поле/форму» — у розділі «Тест-дизайн».
Що ним насправді перевіряють
Чому взагалі змушують кодити наживо, а не надсилають задачу поштою? Бо письмове тестове завдання (тестове завдання) показує результат, а лайвкодинг показує шлях. Інтерв'юер моделює робочу ситуацію — маленьку фічу, за розв'язанням якої можна спостерігати в реальному часі — і дивиться на речі, які в готовому коді не видно:
- декомпозиція — чи розіб'єш велику задачу на маленькі перевірні кроки;
- комунікація — чи проговорюєш, що робиш і чому, чи мовчиш;
- реакція на нову інформацію — підказку, уточнення, зміну вимог посеред задачі;
- інженерна гігієна — крайові випадки, зрозумілі назви змінних, чи перевіряєш власний код перед тим, як сказати «готово».
Що інтерв'юер пробачає: забутий синтаксис, переплутану назву методу, звернення до документації, неоптимальний перший підхід. Що він не пробачає: мовчання, відмову почати, код «на автопілоті» без жодної думки про крайові випадки.
Звідси головний, контрінтуїтивний висновок: правильний, але мовчазний розв'язок часто програє неідеальному, але добре проговореному. Бал ставлять за думання, яке видно, а не за думання, яке відбулося у тебе в голові.
Три формати лайвкодингу
Під «лайвкодингом для AQA» ховаються три різні жанри, і готуватися до них треба по-різному:
| Формат | Що просять | Що перевіряють насамперед |
|---|---|---|
| Алгоритмічна задача | Написати функцію: реверс рядка, дублікати в масиві, retry-обгортку | Біглість у мові, крайові випадки, декомпозиція |
| Автотест наживо | Написати локатор або тест на живу сторінку | Стратегію локаторів, очікування, структуру тесту |
| Рев'ю коду | Знайти проблеми в готовому шматку тесту | Чи бачиш флак і крихкість, чи пояснюєш «чому» |
Далі — про кожен формат окремо: що саме дають, на що дивляться і де підстелити соломки.
Формат 1: алгоритмічна задача
Це найближче до класичного програмістського лайвкодингу, але для QA задачі майже завжди прикладні, а не олімпіадні. Динамічного програмування чи графів тут майже не буває — натомість дають те, що ти реально робиш у тестовому коді щодня. Типові категорії (повний банк із розв'язками — у розділі «JavaScript/TypeScript для AQA»):
- рядки — реверс, паліндром, частотний словник символів чи слів;
- масиви — дублікати, унікальні значення, перетин двох масивів, сортування об'єктів;
- масив об'єктів як тестові дані — відфільтрувати, згрупувати, порахувати агрегат (типовий кейс: «ось список замовлень — порахуй суму по кожному статусу»);
- асинхронні задачі — retry із затримкою, послідовні запити, обмеження паралельності;
- FizzBuzz-клас — прості задачі на розгалуження, щоб просто побачити, що ти пишеш синтаксично коректний код.
Чому саме ці, а не абстрактні LeetCode-задачі: вони дзеркалять роботу AQA — трансформувати тестові дані, дедуплікувати, полінгом дочекатися async-стану. Рівень очікувань зростає з грейдом: від trainee/junior чекають рядки й масиви, від middle — впевнену роботу з масивами об'єктів і async.
Ключове тут не сам розв'язок, а порядок дій. Погано: почути задачу й одразу почати друкувати. Добре: спершу вголос уточнити й навести приклад.
// Задача: порахувати, скільки разів кожне слово трапляється в рядку.
// Проговорюємо ВГОЛОС перед кодом:
// - регістр враховуємо? ("The" і "the" — одне слово чи різні?)
// - розділювач лише пробіл, чи ще пунктуація/переноси?
// - порожній рядок → повертаємо порожній об'єкт, не падаємо.
function wordFrequency(input: string): Record<string, number> {
const counts: Record<string, number> = {};
for (const word of input.toLowerCase().split(/\s+/).filter(Boolean)) {
counts[word] = (counts[word] ?? 0) + 1;
}
return counts;
}
Наївне робоче рішення на цьому етапі важливіше за елегантне. Спершу зроби, щоб працювало, вголос назви крайові випадки — і лише потім, якщо лишається час, оптимізуй.
Формат 2: «напиши локатор / тест для сторінки»
Це специфічно AQA-формат, якого немає у програмістів. Інтерв'юер відкриває реальну сторінку (часто демо-застосунок або твій же pet-проєкт) і просить: «напиши локатор для цієї кнопки» або «напиши тест, що логіниться й перевіряє, що відкрився дашборд». Тут дивляться не на алгоритми, а на інженерну зрілість автоматизатора:
- стратегія локаторів — чи береш стабільні, орієнтовані на користувача локатори (
getByRole,getByLabel,getByText) замість крихких CSS/XPath, прив'язаних до верстки; чи розумієшdata-testidяк контракт із розробкою. Механіка селекторів і DOM — у главі DOM, селектори та події; повна стратегія стабільних локаторів — у розділі «Автоматизація: стратегія». - очікування — чи використовуєш web-first assertions з авто-очікуванням замість
waitForTimeoutіз магічним числом. Чому хардкодні паузи породжують флак — у главі практичні сценарії AQA: флак і синхронізація, а чому SPA завантажується не миттєво — у главі асинхронне завантаження. - структура — AAA (arrange–act–assert), одна перевірка інваріанта, а не god-тест на пів екрана;
- уточнення — який браузер, чи є
data-testid, чи можна логінитися через API замість UI.
Порівняй два локатори на одну й ту саму кнопку — інтерв'юер побачить різницю миттєво:
// Крихко: зламається від зміни верстки чи згенерованого класу
await page.locator('div.form > button.btn-primary:nth-child(3)').click();
// Стабільно: прив'язка до ролі й доступного імені
await page.getByRole('button', { name: 'Увійти' }).click();
А ось мінімальний, але «дорослий» тест — його структуру видно з першого погляду:
test('успішний вхід відкриває дашборд', async ({ page }) => {
// Arrange
await page.goto('/login');
// Act
await page.getByLabel('Email').fill('user@example.com');
await page.getByLabel('Пароль').fill('correct-horse');
await page.getByRole('button', { name: 'Увійти' }).click();
// Assert — web-first, з авто-очікуванням, без ручних пауз
await expect(page.getByRole('heading', { name: 'Дашборд' })).toBeVisible();
});
Якщо стек команди — CodeceptJS, той самий тест виглядатиме як сценарій I.amOnPage, I.fillField, I.click, I.see, але критерії ті самі: семантичні локатори й жодних штучних затримок.
Формат 3: рев'ю коду
Тобі показують готовий шматок тесту й питають: «що тут не так?». Це перевірка не на те, чи напишеш ти код, а чи бачиш проблеми стабільності й підтримуваності. Типовий підсаджений набір дефектів:
- забутий
awaitперед асинхронною дією (floating promise) — тест «пробігає» повз перевірку; waitForTimeout(5000)замість очікування конкретної умови;- локатор через
nth(2)або абсолютний XPath; - тест, що залежить від стану, який лишив попередній тест (порушена ізоляція);
- перевірка без зрозумілого повідомлення, хардкод тестових даних, відсутність прибирання.
Що оцінюють: чи ти не просто тицяєш пальцем «це погано», а пояснюєш чому (цей waitForTimeout закладає флак і сповільнює прогін) і пропонуєш конкретний фікс (замінити на web-first assertion). Таксономія причин флаку й політика боротьби з ним — у розділі «Автоматизація: стратегія».
Мислення вголос і декомпозиція
Це головна мета-навичка, заради якої весь етап і існує. Універсальний шаблон, що працює для будь-якого формату лайвкодингу:
Тактика проговорювання проста: кажи, що збираєшся зробити, перед тим, як це зробити. «Спершу уточню: рядок може бути порожній? Юнікод рахуємо як окремі символи? Добре, тоді пройдуся по символах і складатиму словник частот». Інтерв'юер чує хід думки — і навіть якщо ти застрягнеш на синтаксисі, він уже знає, що логіку ти тримаєш.
Крайові випадки — це той чекліст, який QA має називати сам, не чекаючи підказки. Промовляй їх уголос: порожній ввід, null/undefined, дуже великий ввід, дублікати, юнікод і пробіли, від'ємні числа, а для async — таймаут, помилка й порожній список. Саме тут кандидат-тестувальник має перевагу над кандидатом-розробником: думати про те, що зламається, — твоя основна робота.
Реакція на підказки
Підказка від інтерв'юера — це сигнал і допомога, а не вирок. Її дають, щоб зрушити тебе з місця й побачити, чи вмієш ти вбудувати нову інформацію — рівно так, як вбудовуватимеш коментарі рев'юера в реальній роботі. Дві протилежні реакції розводять кандидатів на різні полюси:
- Погано — проігнорувати підказку й уперто йти своїм шляхом, або розгубитися й замовкнути.
- Добре — «О, дякую — тобто ви натякаєте, що замість вкладеного циклу тут можна
Mapі звести до одного проходу? Так, це прибирає квадратичну складність».
Уміння вдячно взяти підказку — це позитивний сигнал: воно каже, що з тобою легко працювати в парі. Оборона від підказки, навпаки, читається як «з цим кандидатом кожне рев'ю буде боєм».
Тактика при застряганні
Застрягнути — нормально; на це дивляться не менш уважно, ніж на гладкий розв'язок, бо в роботі ти теж застрягатимеш. Помилка лише одна — застрягнути мовчки. Порядок дій:
Розкладемо словами:
- Проговори затик — «я знаю, що треба згрупувати замовлення за статусом, але не пригадаю точний синтаксис
reduce». Це і чесно, і дає інтерв'юеру точку, де підключитися. - Спрости — розв'яжи меншу версію: не «згрупуй і порахуй агрегат», а спершу «просто відфільтруй один статус».
- Напиши наївне робоче рішення — навіть на подвійному циклі. Робоче
O(n²)б'є елегантне неробоче. - Попроси підказку прямо — якщо реально глухо. Це не мінус; мовчазні п'ять хвилин у стелю — мінус.
- Перевір те, що вже є — прожени свій код на прикладі замість тупцювати на місці.
Як тренуватись
- Регулярно й уголос. Розв'язуй задачі, промовляючи вголос або записуючи себе на диктофон. Тиша на реальній співбесіді — від нетренованості говорити й кодити одночасно, а не від незнання.
- Знай мову руками. Методи масивів (
map/filter/reduce/find),Promise(all/allSettled),async/awaitмають згадуватися без гуглінгу базового — це «мова», якою ти пишеш. Матеріал — у розділі «JavaScript/TypeScript для AQA». - Тренуйся в тому середовищі, де проситимуть. Часто це середовище бідніше за звичну IDE: онлайн-редактор на кшталт CoderPad, спільний Google Docs або шматок Playwright-проєкту. Порепетируй без милиць IDE.
- Мок-співбесіди з таймером. Штучний тиск часу — окрема навичка; як його відпрацювати, — у главі план підготовки і mock-співбесіди.
- Розбирай власний фреймворк. Багато AQA-лайвкодингів — це «покажи, як ти пишеш тест» на твоєму ж стеку. Умій пояснити кожне рішення у своєму проєкті — це також місток до технічної співбесіди AQA.
Типові помилки
- Мовчазний геній — виглядає як зосередженість, а насправді інтерв'юер не бачить твого мислення й ставить нижчий бал, ніж за гірший, але проговорений розв'язок.
- Кинувся кодити одразу — виглядає як упевненість, а насправді пропустив уточнення й розв'язав не ту задачу.
- Ігнорування крайових випадків — виглядає як «основне ж працює», а насправді для QA-ролі саме крайові випадки — твій хліб; пропустити їх на лайвкодингу тобі гірше, ніж кандидатові-розробнику.
- Оборона від підказки — виглядає як принциповість, а насправді сигнал, що з тобою важко працювати в парі.
waitForTimeoutіforce: trueу тесті — виглядає як «зробив, щоб працювало», а насправді демонструє нерозуміння авто-очікувань і закладає майбутній флак.- Передчасна оптимізація — виглядає як сеньйорність, а насправді ти витрачаєш час на «найкращий алгоритм» замість спершу зробити робочий.
Підсумок
- Лайвкодинг перевіряє процес, а не відповідь: думай уголос, інакше твоє мислення просто не зарахують.
- Спершу уточни вимоги й наведи приклад входу/виходу, і лише потім кодь.
- Крайові випадки називай сам — для QA це головна перевага над кандидатом-розробником.
- Підказка — це допомога й позитивний сигнал; бери її вдячно, не обороняйся.
- Робоче наївне рішення б'є елегантне неробоче: спершу «щоб працювало», оптимізація — потім.
Що питають на співбесіді
- «Напишіть функцію, що рахує, скільки разів кожне слово трапляється в рядку.» — Дивляться, чи згадаєш крайові випадки (порожній рядок, регістр, пунктуація) і чи проговорюєш хід.
- «Ось сторінка логіну — напишіть тест, що вводить дані й перевіряє вхід.» — Дивляться на стратегію локаторів, очікування без хардкодних пауз і структуру AAA.
- «Що не так у цьому тесті?» (зі схованим
waitForTimeoutіnth-локатором) — Дивляться, чи бачиш джерела флаку й чи пояснюєш, чому це погано, а не лише «перепиши». - «Розверніть рядок / знайдіть дублікати в масиві.» — Дивляться на базову біглість у методах мови без гуглінгу елементарного.
- «Напишіть retry-функцію, що повторює запит N разів із затримкою.» — Дивляться на
async/await, обробку помилок і чи не загубив тиawait.
На що дивиться інтерв'юер загалом: не на ідеальний код, а на озвучені припущення, названі крайові випадки й спокійну реакцію на затик. Сказати вголос «я не пам'ятаю точну сигнатуру, гляну в доку» — нормально й навіть плюс; вдавати, що знаєш, і писати навмання — мінус.
Джерела
- Playwright — Best Practices — орієнтовані на користувача локатори, ізоляція тестів, web-first assertions, чому не потрібні ручні паузи.
- Playwright — Locators —
getByRole/getByLabel/getByText/getByTestIdі пріоритет стабільних селекторів. - MDN — Array — методи
map/filter/reduce/findдля задач із тестовими даними. - MDN — Promise —
all/allSettled/raceдля async-задач на кшталт retry й обмеження паралельності.
Ця тема не входить до силабусу ISTQB CTFL 4.0 — це інженерна практика, а не частина тестувальницької теорії; змістовний матеріал з мови й автотестів шукай у розділах «JavaScript/TypeScript для AQA» та «Інструменти автоматизації».
Що таке лайвкодинг на співбесіді AQA і навіщо він, якщо є тестове завдання?
Лайвкодинг (live coding) — це коли ти пишеш код прямо на співбесіді, при інтерв'юері, який спостерігає за процесом у реальному часі: невелика функція, тест на живу сторінку або розбір чужого коду. Сенс саме в спостереженні: письмове тестове завдання показує лише кінцевий результат, а лайвкодинг відкриває шлях до нього. Інтерв'юер бачить те, що в готовому коді вже стерто, — як ти уточнюєш умову, звідки починаєш, коли згадуєш про крайовий випадок. Тому це не заміна тестового, а інший зріз: не «що ти вмієш написати», а «як ти думаєш, коли пишеш».
Що насправді оцінюють на лайвкодингу, якщо не ідеальність коду?
Оцінюють процес мислення, а не бездоганність результату. Конкретно дивляться на чотири речі: декомпозицію (чи ділиш велику задачу на дрібні перевірні кроки), комунікацію (чи проговорюєш свої дії), реакцію на нову інформацію (підказку, уточнення, зміну вимог) та інженерну гігієну (крайові випадки, зрозумілі назви, самоперевірку перед «готово»). Ідеальний код — приємний бонус, але інтерв'юер уже бачив сотні реалізацій FizzBuzz, і його цікавить не відповідь. Через це буквально можлива ситуація, коли робочий, але мовчазний розв'язок отримує нижчий бал, ніж кривуватий, але добре проговорений.
Що інтерв'юер на лайвкодингу пробачає, а що — ні?
Пробачають технічні дрібниці: забутий синтаксис, переплутану назву методу, звертання до документації, перший неоптимальний підхід. Усе це нормально, бо в реальній роботі ти теж гуглиш сигнатуру й переписуєш перший варіант. Не пробачають натомість поведінкові речі: мовчання, відмову почати, код «на автопілоті» без жодної згадки про те, що може зламатися. Простими словами: помилка в коді — дрібниця, а от відсутність видимого мислення — це те, за що знижують бал.
Чому правильний, але мовчазний розв'язок може програти неідеальному, але проговореному?
Бо бал ставлять за мислення, яке інтерв'юер побачив, а не за те, що відбулося у тебе в голові. Якщо ти мовчки написав робочу функцію, для спостерігача це чорна скринька: він не знає, чи ти вивів логіку сам, чи згадав завчений шаблон, чи вгадав. А коли ти вголос перебираєш варіанти, називаєш крайові випадки й пояснюєш вибір, він бачить інженера в роботі — навіть якщо фінальний код з дрібним багом. Мовчазна досконалість не конвертується в бал, бо її нема як зарахувати.
Які три формати лайвкодингу бувають в AQA і чим вони відрізняються?
Під однією назвою ховаються три різні жанри. Перший — алгоритмічна задача: написати невелику функцію (реверс рядка, пошук дублікатів, retry-обгортка), тут дивляться на біглість у мові й крайові випадки. Другий — автотест наживо: написати локатор або тест на реальну сторінку, тут перевіряють стратегію локаторів, очікування й структуру тесту. Третій — рев'ю коду: знайти проблеми в готовому шматку тесту, тут важливо, чи бачиш ти джерела флаку й чи пояснюєш «чому». Готуватися до них треба по-різному, бо перевіряють вони різні навички.
Які алгоритмічні задачі типові саме для QA-лайвкодингу і чому не LeetCode?
Задачі майже завжди прикладні, а не олімпіадні: динамічного програмування чи графів практично не буває. Натомість дають те, що ти робиш у тестовому коді щодня — операції над рядками (реверс, паліндром, частотний словник), над масивами (дублікати, унікальні, перетин), трансформації масиву об'єктів як тестових даних (відфільтрувати, згрупувати, порахувати агрегат), асинхронні задачі (retry із затримкою, обмеження паралельності) та прості FizzBuzz-подібні на розгалуження. Причина проста: ці задачі дзеркалять реальну роботу автоматизатора, тоді як абстрактний LeetCode перевіряв би навичку, яку AQA майже не застосовує. Рівень очікувань росте з грейдом: від джуна чекають рядки й масиви, від мідла — впевнену роботу з масивами об'єктів і async.
Який правильний порядок дій, коли тобі дали алгоритмічну задачу?
Спершу уточнити, потім кодити — не навпаки. Погана послідовність: почути умову й одразу почати друкувати, бо так легко розв'язати не ту задачу. Добра: проговорити вголос відкриті питання (чи враховуємо регістр, який роздільник, що робити з порожнім вводом), навести приклад входу й очікуваного виходу, накидати наївне робоче рішення, прогнати його на крайових випадках і лише потім, якщо лишається час, оптимізувати. Наївний робочий варіант на цьому етапі цінніший за елегантний: спочатку «щоб працювало», краса — потім. Такий порядок показує інтерв'юеру системне мислення, а не рефлекс друкувати.
До тебе відкрили живу сторінку й просять написати локатор. З чого почати і на що дивляться?
Дивляться на інженерну зрілість автоматизатора, а не на алгоритми. Перед кодом варто уточнити контекст: який браузер, чи є на елементах data-testid, чи можна логінитися через API замість UI. Далі — стратегія локаторів: брати стабільні, орієнтовані на користувача селектори (getByRole, getByLabel, getByText) замість крихких CSS чи XPath, прив'язаних до верстки. Окремо оцінюють очікування — чи використовуєш web-first assertions з авто-очікуванням замість пауз із магічним числом — і структуру тесту за схемою arrange–act–assert. Тобто перевіряють не «чи знайдеш ти елемент узагалі», а чи знайдеш стабільно й підтримувано.
Чому getByRole('button', { name: 'Увійти' }) кращий за div.form > button.btn-primary:nth-child(3)?
Бо перший локатор прив'язаний до того, що бачить і чим користується людина (роль елемента й доступне ім'я), а другий — до структури верстки й згенерованих класів, які змінюються від будь-якого рефакторингу CSS чи перестановки блоків. CSS-ланцюжок із nth-child зламається, щойно дизайнер додасть обгортку або поміняє порядок кнопок, хоча функціонально сторінка та сама. Рольовий локатор переживе таку зміну, бо кнопка «Увійти» лишається кнопкою «Увійти». Для інтерв'юера це миттєвий сигнал: кандидат розуміє, звідки береться крихкість тестів, і пише на підтримку, а не «аби знайшло зараз».
Чому waitForTimeout(5000) у тесті — поганий знак на лайвкодингу?
Бо це фіксована пауза на магічне число, яка не пов'язана з реальною подією на сторінці. Вона одночасно й сповільнює прогін (чекаєш повні п'ять секунд, навіть коли елемент з'явився за 200 мс), і не рятує від флаку (на повільному CI п'яти секунд може не вистачити). Правильна альтернатива — web-first assertion з авто-очікуванням, яка чекає рівно стільки, скільки треба, і падає з осмисленою помилкою, коли умова так і не настала. Коли кандидат ставить waitForTimeout замість очікування конкретної умови, це читається як нерозуміння того, як працює авто-очікування, і закладена міна майбутнього флаку.
Формат «рев'ю коду»: які дефекти зазвичай підсаджують і що оцінюють?
Підсаджують типовий набір джерел флаку й крихкості: забутий await перед асинхронною дією (floating promise, через який тест «пробігає» повз перевірку), waitForTimeout замість очікування умови, локатор через nth(2) або абсолютний XPath, залежність від стану, який лишив попередній тест (порушена ізоляція), а також перевірку без зрозумілого повідомлення й хардкод тестових даних. Оцінюють не сам факт «тицьнув пальцем, що погано», а чи пояснюєш ти, чому це погано (цей waitForTimeout сповільнює прогін і закладає флак), і чи пропонуєш конкретний фікс (замінити на web-first assertion). Тобто перевіряють, чи бачиш ти проблему системно, а не за списком «поганих слів».
Навіщо проговорювати думки вголос і як це робити правильно?
Проговорювання — це головна мета-навичка, заради якої весь етап існує, бо воно робить твоє мислення видимим. Правило просте: кажи, що збираєшся зробити, перед тим як це зробити. Наприклад: «спершу уточню, чи рядок може бути порожнім і чи рахуємо юнікод окремими символами; далі пройдуся по символах і складатиму словник частот». Так інтерв'юер чує хід думки, і навіть якщо ти застрягнеш на синтаксисі, він уже бачить, що логіку ти тримаєш. Тиша ж лишає його наодинці з порожнім екраном, де нема що оцінювати.
Які крайові випадки треба називати самому і чому це перевага QA-кандидата?
Називати варто повний типовий набір, не чекаючи підказки: порожній ввід, null/undefined, дуже великий ввід, дублікати, юнікод і пробіли, від'ємні числа, а для асинхронних задач — таймаут, помилку й порожній список. Робити це треба вголос, у момент постановки задачі, а не коли інтерв'юер сам про них спитає. Саме тут тестувальник має структурну перевагу над кандидатом-розробником: думати про те, що зламається, — його основна професійна навичка, тому пропустити крайові випадки для AQA гірше, ніж для програміста. Названі вголос граничні умови — один із найсильніших сигналів, що перед інтерв'юером саме QA-інженер.
Інтерв'юер дав підказку. Як на неї реагувати?
Підказка — це сигнал і допомога, а не вирок і не «ти провалився». Її дають, щоб зрушити тебе з місця й побачити, чи вмієш ти вбудувати нову інформацію — рівно так, як вбудовуватимеш коментарі рев'юера в реальній роботі. Правильна реакція — вдячно взяти й одразу застосувати: «дякую, тобто замість вкладеного циклу тут краще Map за один прохід — так, це прибирає квадратичну складність». Погана — проігнорувати підказку й уперто йти своїм шляхом або розгубитися й замовкнути. Уміння прийняти підказку читається як «з цим кандидатом легко працювати в парі», а оборона від неї — як «кожне рев'ю буде боєм».
Ти застряг посеред задачі. Що робити?
Застрягнути — нормально, на це дивляться не менш уважно, ніж на гладкий розв'язок, бо в роботі ти теж застрягатимеш. Єдина справжня помилка — застрягнути мовчки. Порядок дій такий: проговори, де саме затик («знаю, що треба згрупувати за статусом, але не пригадаю синтаксис reduce»); спрости задачу до меншої версії (спершу просто відфільтруй один статус); напиши наївне робоче рішення, хай навіть на подвійному циклі, бо робоче O(n²) б'є елегантне неробоче; якщо реально глухо — прямо попроси підказку; і прожени те, що вже написав, на прикладі замість тупцювати на місці. Мовчазні п'ять хвилин у стелю коштують дорожче за чесне «я застряг ось тут».
Як тренуватися до лайвкодингу, щоб не завалити його від хвилювання?
Тиша на реальній співбесіді частіше йде від нетренованості говорити й кодити одночасно, ніж від незнання, тому тренувати треба саме цю пару навичок. Розв'язуй задачі вголос або записуючи себе на диктофон, щоб проговорювання стало звичкою. Доведи до автоматизму базову «мову»: методи масивів (map/filter/reduce/find), Promise.all/allSettled, async/await мають згадуватися без гуглінгу елементарного. Тренуйся в тому середовищі, де проситимуть, — часто це середовище бідніше за звичну IDE (онлайн-редактор на кшталт CoderPad, спільний документ), тож порепетируй без милиць. І додай мок-співбесіди з таймером, бо штучний тиск часу — окрема навичка, а ще навчись пояснювати кожне рішення у власному фреймворку, бо багато AQA-лайвкодингів — це «покажи, як ти пишеш тест» на твоєму ж стеку.
Які типові помилки на лайвкодингу і чому кожна виглядає не тим, чим є?
Найпоширеніші п'ять. «Мовчазний геній» виглядає як зосередженість, а насправді ховає мислення й тягне бал вниз. «Кинувся кодити одразу» виглядає як упевненість, а насправді пропускає уточнення й веде до розв'язання не тієї задачі. Ігнорування крайових випадків виглядає як «основне ж працює», а для QA-ролі саме гранична поведінка — головний хліб. Оборона від підказки виглядає як принциповість, а читається як складність у парній роботі. Передчасна оптимізація виглядає як сеньйорність, а насправді з'їдає час, який мав піти на робочий варіант. Спільне в усіх — правильна на вигляд поведінка, що працює проти кандидата.
Три кейси, що показують лайвкодинг з боку інтерв'юера: як звучить та сама задача в мовчазній і в проговореній версії, як розібрати підсаджений у рев'ю флак і як «сигнали» кандидата читаються в бал. Мета — не розв'язки задач (їх банк живе в розділі про JS/TS), а поведінка навколо коду.
Кейс 1. Одна задача, дві доріжки: мовчання проти проговорювання
Задача на екрані: «напиши функцію, що повертає слова рядка, відсортовані за спаданням частоти». Розв'язок в обох доріжках майже однаковий — різниця лише в тому, що чує інтерв'юер.
Доріжка А (мовчазна): кандидат хвилину дивиться в екран, потім друкує готову функцію без жодного слова, наприкінці каже «готово». Код навіть робочий. Але для спостерігача це чорна скринька: незрозуміло, чи врахований регістр, чи впаде воно на порожньому рядку, чи кандидат вивів логіку сам, чи згадав завчений шаблон. Оцінити нема чого, крім фінального тексту.
Доріжка Б (проговорена): той самий кандидат спершу вголос збирає умову.
// Проговорюю ВГОЛОС, поки думаю:
// - "The" і "the" — одне слово чи різні? Питаю → домовились: регістр не важливий.
// - розділювач лише пробіл чи ще пунктуація? → поки що пробіли й переноси.
// - порожній рядок → повертаю [], не падаю.
// - при однаковій частоті порядок слів не гарантую (уточнюю, що це ок).
function wordsByFrequency(input: string): string[] {
const counts = new Map<string, number>();
for (const w of input.toLowerCase().split(/\s+/).filter(Boolean)) {
counts.set(w, (counts.get(w) ?? 0) + 1);
}
return [...counts.entries()]
.sort((a, b) => b[1] - a[1])
.map(([word]) => word);
}
Далі кандидат сам себе перевіряє: «прожену на "a a b" — очікую ["a", "b"]; на "" — очікую [], бо filter(Boolean) прибирає порожні токени». Код той самий, але тепер інтерв'юер бачить інженера в роботі: названі припущення, названі крайові випадки, самоперевірка перед «готово».
Що дивитися і чому:
- Бал ставлять за доріжкою Б, навіть якщо в ній лишиться дрібний баг. Видиме мислення можна зарахувати, мовчазну досконалість — ні.
- Уточнення регістру й порожнього вводу — не формальність. Це показує, що кандидат думає про вхід, а не одразу про вихід; для QA це базовий рефлекс.
- Самоперевірка на прикладі замість «готово». Прогнати функцію очима на двох входах коштує 10 секунд і знімає половину питань інтерв'юера.
Кейс 2. Рев'ю коду: знайти флак і проговорити «чому»
Формат «що тут не так?». Тобі дають шматок Playwright-тесту з підсадженими дефектами. Завдання — не переписати мовчки, а назвати кожну проблему, пояснити наслідок і запропонувати фікс.
// Версія, яку показують на рев'ю — знайди все, що закладає флак:
test('checkout', async ({ page }) => {
page.goto('/cart'); // 1
await page.waitForTimeout(3000); // 2
await page.locator('.row:nth-child(2) button').click(); // 3
await page.getByRole('button', { name: 'Pay' }).click();
await page.waitForTimeout(2000); // 2
expect(page.getByText('Order #12345')).toBeVisible(); // 4, 5
});
Як це звучить у сильного кандидата — по пунктах, з наслідком і фіксом:
- Забутий
awaitпередpage.goto. Floating promise: навігація може ще не завершитися, а тест уже біжить далі. Фікс — додатиawait. waitForTimeout(3000)іwaitForTimeout(2000). Магічні паузи: повільні, коли елемент готовий раніше, і ненадійні, коли CI гальмує. Фікс — прибрати обидві, покластися на авто-очікування web-first assertion.- Локатор
.row:nth-child(2) button. Прив'язка до позиції в списку: додасться рядок — тест клікне не туди. Фікс — семантичний локатор абоdata-testidна потрібній кнопці. - Забутий
awaitпередexpect. Web-first assertion асинхронна; безawaitперевірка не чекає й фактично не виконується — тест «зелений» примарно. - Хардкод
Order #12345. Номер замовлення генерується, тож жорсткий рядок або впаде, або (гірше) пройде хибно. Фікс — перевіряти патерн/Order #\d+/чи брати очікуване значення з відповіді API.
// Як має виглядати після рев'ю:
test('успішний checkout показує номер замовлення', async ({ page }) => {
await page.goto('/cart');
await page.getByTestId('remove-item').first().click();
await page.getByRole('button', { name: 'Pay' }).click();
await expect(page.getByText(/Order #\d+/)).toBeVisible();
});
Що дивитися і чому:
- Оцінюють пояснення, а не список. «Тут
waitForTimeout— погано» коштує мало; «ця пауза сповільнює прогін і на повільному CI не врятує, замінюю на авто-очікування» — це і є сигнал зрілості. - Два різні
await-дефекти легко злити в один. Забутийawaitна дії (goto) і на перевірці (expect) мають різний наслідок: перший — гонка, другий — перевірка, що фактично не виконалась. - Хардкод даних — не косметика. Він або ламає тест, або дає хибнозелений результат, що небезпечніше за падіння.
Кейс 3. Таблиця сигналів: як поведінка кандидата читається в бал
Інтерв'юер оцінює не тільки код, а й серію мікросигналів. Ось як типові з них конвертуються в оцінку — корисно тримати перед очима, коли готуєшся.
| Поведінка кандидата | Як читає інтерв'юер | Куди тягне бал |
|---|---|---|
| Уточнив умову й навів приклад входу/виходу до коду | Системне мислення, не розв'язує не ту задачу | Вгору |
| Назвав крайові випадки сам, без підказки | Профільний QA-рефлекс | Вгору |
| Вдячно взяв підказку й одразу застосував | Легко працювати в парі | Вгору |
| Чесно сказав «застряг ось тут, гляну в доку» | Самоусвідомлення, а не блеф | Вгору |
| Мовчки написав робочий код | Чорна скринька, мислення не видно | Вниз |
| Кинувся друкувати одразу після умови | Пропустив уточнення, ризик не тієї задачі | Вниз |
| Проігнорував або відкинув підказку | Складний у парній роботі | Вниз |
| Хвилини мовчання в затику | Не видно, де саме проблема | Вниз |
| Одразу шукає «найкращий алгоритм» замість робочого | Передчасна оптимізація, з'їдає час | Вниз |
Головний висновок таблиці: майже кожен «мінусовий» рядок виглядає ззовні як щось хороше — упевненість, принциповість, зосередженість, сеньйорність. Пастка саме в цьому, тому на тренуванні варто ловити себе не на помилках у коді, а на цих оманливих на вигляд патернах поведінки.
Що перевіряє лайвкодинг
- Розумію, що оцінюють процес мислення, а не бездоганність коду, і можу пояснити чотири осі: декомпозиція, комунікація, реакція на нову інформацію, інженерна гігієна.
- Можу сформулювати, чому лайвкодинг існує поряд із тестовим завданням: тестове показує результат, лайвкодинг — шлях до нього.
- Знаю, що інтерв'юер пробачає (забутий синтаксис, звертання до доки, перший неоптимальний підхід) і чого не пробачає (мовчання, відмову почати, код без думки про крайові випадки).
- Розумію контрінтуїтивне: робочий, але мовчазний розв'язок може отримати нижчий бал, ніж кривуватий, але проговорений.
Три формати
- Розрізняю три жанри лайвкодингу — алгоритмічна задача, автотест наживо, рев'ю коду — і знаю, що кожен перевіряє інші навички.
- Знаю, що QA-алгоритми прикладні, а не олімпіадні: рядки, масиви, масив об'єктів як тестові дані, async (retry, паралельність), FizzBuzz-клас — не графи й не DP; вони дзеркалять роботу AQA (трансформувати дані, дедуплікувати, дочекатися async-стану), а не абстрактний LeetCode.
- Пам'ятаю, що рівень очікувань росте з грейдом: джуну — рядки й масиви, мідлу — впевнений async і масиви об'єктів.
Стратегія локаторів і структура тесту
- Можу пояснити, чому семантичний локатор (
getByRole,getByLabel,getByText) стабільніший за CSS/XPath іnth-child, прив'язані до верстки, і розуміюdata-testidяк контракт із розробкою, а не «ще один селектор». - Знаю, чому
waitForTimeoutіз магічним числом гірший за web-first assertion: одночасно повільний і не рятує від флаку. - Тримаю в голові структуру тесту arrange–act–assert та принцип «одна перевірка інваріанта», а не god-тест на пів екрана.
- Знаю, які уточнення доречні перед тестом: браузер, наявність
data-testid, чи можна логінитися через API замість UI.
Рев'ю коду: що шукати
- Впізнаю джерела флаку в чужому тесті: забутий
await(floating promise), через який тест «пробігає» повз перевірку,waitForTimeoutзамість очікування умови, крихкий локатор черезnth/абсолютний XPath і порушену ізоляцію стану між тестами. - Розумію, що оцінюють не «тицьнув, що погано», а пояснення «чому» плюс конкретний фікс.
Мислення вголос і крайові випадки
- Тримаю правило: кажу, що збираюся зробити, перед тим як це зробити.
- Знаю базовий чек-ліст крайових випадків, який називаю сам (порожній ввід,
null/undefined, великий ввід, дублікати, юнікод і пробіли, від'ємні числа, а для async — таймаут, помилка, порожній список), і чому названі вголос граничні умови — головна перевага QA над кандидатом-розробником. - Пам'ятаю порядок: уточнити → приклад входу/виходу → наївне робоче рішення → прогнати крайові → лише потім оптимізувати.
Підказки, застрягання, підготовка
- Розумію, що підказка — це допомога й позитивний сигнал; беру її вдячно й одразу застосовую, а не обороняюся.
- Знаю алгоритм при застряганні: проговори затик → спрости до меншого випадку → напиши наївний робочий варіант → попроси підказку прямо → перевір на прикладі; мовчати не можна.
- Пам'ятаю, що робоче
O(n²)б'є елегантне неробоче, і можу перелічити типові фейли (кожен оманливий на вигляд): мовчазний геній, кинувся кодити одразу, ігнор крайових, оборона від підказки, передчасна оптимізація. - Знаю, як тренуватись: вголос/на диктофон, базова «мова» без гуглінгу, «голий» редактор без IDE, мок-співбесіди з таймером, розбір власного фреймворку.
Що насправді оцінюють на лайвкодингу AQA?
Питання
Що таке лайвкодинг (live coding) на співбесіді AQA?