Лайвкодинг для AQA
Зміст
(live coding) — це коли на технічній співбесіді тебе просять писати код прямо зараз, з інтерв'юером за плечем: розв'язати невелику задачку, накидати автотест на живу сторінку або розібрати чужий код. Для більшості кандидатів, що переходять з мануального тестування в автоматизацію, це найстрашніший етап — не тому, що задачі складні, а тому, що доводиться думати вголос під наглядом, і будь-яка пауза здається провалом.
Головне непорозуміння, через яке валяться навіть сильні кандидати: лайвкодинг перевіряє не те, чи напишеш ти ідеальний код без єдиної помилки. Він перевіряє, як ти думаєш — чи вмієш розкласти задачу, поставити уточнювальні питання, згадати , зреагувати на підказку. Робочий код — приємний бонус, але інтерв'юер бачив сотні розв'язків FizzBuzz; його цікавить процес, а не відповідь. Ця глава — про формати, критерії оцінки й тактику, а не про самі задачі: банк алгоритмічних задач із розв'язками живе в розділі «JavaScript/TypeScript для AQA» (глава про live coding), а розбір «протестуй поле/форму» — у розділі «Тест-дизайн».
Що ним насправді перевіряють
Наша практика (не канон). Далі — те, як цей етап пояснюють інтервʼюери, з якими ми працювали: лайвкодинг як прийом добору жодне джерело нашого реєстру не описує, а критеріїв оцінки не публікує ніхто.
Чому взагалі змушують кодити наживо, а не надсилають задачу поштою? Бо письмове (тестове завдання) показує результат, а лайвкодинг показує шлях. Інтерв'юер моделює робочу ситуацію — маленьку фічу, за розв'язанням якої можна спостерігати в реальному часі — і дивиться на речі, які в готовому коді не видно:
- декомпозиція — чи розіб'єш велику задачу на маленькі перевірні кроки;
- комунікація — чи проговорюєш, що робиш і чому, чи мовчиш;
- реакція на нову інформацію — підказку, уточнення, зміну вимог посеред задачі;
- інженерна гігієна — edge cases, зрозумілі назви змінних, чи перевіряєш власний код перед тим, як сказати «готово».
Що інтерв'юер пробачає: забутий синтаксис, переплутану назву методу, звернення до документації, неоптимальний перший підхід. Що він не пробачає: мовчання, відмову почати, код «на автопілоті» без жодної думки про edge cases.
Звідси головний, контрінтуїтивний висновок: правильний, але мовчазний розв'язок часто програє неідеальному, але добре проговореному. Бал ставлять за думання, яке видно, а не за думання, яке відбулося у тебе в голові.
Три формати лайвкодингу
Під «лайвкодингом для AQA» ховаються три різні жанри, і готуватися до них треба по-різному:
| Формат | Що просять | Що перевіряють насамперед |
|---|---|---|
| Алгоритмічна задача | Написати функцію: реверс рядка, дублікати в масиві, retry-обгортку | Біглість у мові, edge cases, декомпозиція |
| Автотест наживо | Написати локатор або тест на живу сторінку | Стратегію локаторів, очікування, структуру тесту |
| Рев'ю коду | Знайти проблеми в готовому шматку тесту | Чи бачиш флак і крихкість, чи пояснюєш «чому» |
Далі — про кожен формат окремо: що саме дають, на що дивляться і де підстелити соломки.
Формат 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;
}
Наївне робоче рішення на цьому етапі важливіше за елегантне. Спершу зроби, щоб працювало, вголос назви edge cases — і лише потім, якщо лишається час, оптимізуй.
Формат 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). Таксономія причин флаку й політика боротьби з ним — у розділі «Автоматизація: стратегія».
Мислення вголос і декомпозиція
Наша практика (не канон). Мислення вголос (think-aloud) — чужий названий метод із власною літературою, але в нашому реєстрі джерел його немає: далі йде наш робочий шаблон, зібраний із практики співбесід, а не виклад методу за першоджерелом.
Це головна мета-навичка, заради якої весь етап і існує. Універсальний шаблон, що працює для будь-якого формату лайвкодингу:
Тактика проговорювання проста: кажи, що збираєшся зробити, перед тим, як це зробити. «Спершу уточню: рядок може бути порожній? Юнікод рахуємо як окремі символи? Добре, тоді пройдуся по символах і складатиму словник частот». Інтерв'юер чує хід думки — і навіть якщо ти застрягнеш на синтаксисі, він уже знає, що логіку ти тримаєш.
Edge cases — це той чекліст, який 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.
- -співбесіди з таймером. Штучний тиск часу — окрема навичка; як його відпрацювати, — у главі план підготовки і мок-співбесіди.
- Розбирай власний фреймворк. Багато AQA-лайвкодингів — це «покажи, як ти пишеш тест» на твоєму ж стеку. Умій пояснити кожне рішення у своєму проєкті — це також місток до технічної співбесіди AQA.
Типові помилки
- Мовчазний геній — виглядає як зосередженість, а насправді інтерв'юер не бачить твого мислення й ставить нижчий бал, ніж за гірший, але проговорений розв'язок.
- Кинувся кодити одразу — виглядає як упевненість, а насправді пропустив уточнення й розв'язав не ту задачу.
- Ігнорування edge cases — виглядає як «основне ж працює», а насправді для QA-ролі саме edge cases — твій хліб; пропустити їх на лайвкодингу тобі гірше, ніж кандидатові-розробнику.
- Оборона від підказки — виглядає як принциповість, а насправді сигнал, що з тобою важко працювати в парі.
waitForTimeoutіforce: trueу тесті — виглядає як «зробив, щоб працювало», а насправді демонструє нерозуміння автоочікувань і закладає майбутній флак.- Передчасна оптимізація — виглядає як сеньйорність, а насправді ти витрачаєш час на «найкращий алгоритм» замість спершу зробити робочий.
Підсумок
- Лайвкодинг перевіряє процес, а не відповідь: думай уголос, інакше твоє мислення просто не зарахують.
- Спершу уточни вимоги й наведи приклад входу/виходу, і лише потім кодь.
- Edge cases називай сам — для QA це головна перевага над кандидатом-розробником.
- Підказка — це допомога й позитивний сигнал; бери її вдячно, не обороняйся.
- Робоче наївне рішення б'є елегантне неробоче: спершу «щоб працювало», оптимізація — потім.
Можливі питання
- «Напишіть функцію, що рахує, скільки разів кожне слово трапляється в рядку.» — Дивляться, чи згадаєш edge cases (порожній рядок, регістр, пунктуація) і чи проговорюєш хід.
- «Ось сторінка логіну — напишіть тест, що вводить дані й перевіряє вхід.» — Дивляться на стратегію локаторів, відсутність жорстких очікувань і структуру AAA.
- «Що не так у цьому тесті?» (зі схованим
waitForTimeoutіnth-локатором) — Дивляться, чи бачиш джерела флаку й чи пояснюєш, чому це погано, а не лише «перепиши». - «Розверніть рядок / знайдіть дублікати в масиві.» — Дивляться на базову біглість у методах мови без гуглінгу елементарного.
- «Напишіть retry-функцію, що повторює запит N разів із затримкою.» — Дивляться на
async/await, обробку помилок і чи не загубив тиawait.
На що дивиться інтерв'юер загалом: не на ідеальний код, а на озвучені припущення, названі edge cases й спокійну реакцію на затик. Сказати вголос «я не пам'ятаю точну сигнатуру, гляну в доку» — нормально й навіть плюс; вдавати, що знаєш, і писати навмання — мінус.
Ця тема не входить до силабусу ISTQB CTFL 4.0 — це інженерна практика, а не частина тестувальницької теорії; змістовний матеріал з мови й автотестів шукай у розділах «JavaScript/TypeScript для AQA» та «Інструменти автоматизації».
Джерела
- Playwright — Locators — орієнтовані на користувача локатори
getByRole,getByLabel,getByText,getByTestId— саме їх тут чекають замість прив'язки до верстки. - Playwright — Best Practices — чому web-first перевірки з автоочікуванням замінюють ручні паузи й навіщо тримати тести ізольованими — рівно те, що підсаджують у задачу на рев'ю коду.
- Testing Library — Guiding Principles — принцип «що ближче тест до способу використання, то більше довіри»: те саме правило в іншого інструмента, тож семантичний локатор — не вподоба Playwright.
- Cypress — Best Practices — третій інструмент із тією самою рекомендацією:
data-*як основна стратегія, щоб ізолювати селектори від змін CSS і JS. - MDN — Use data attributes — чому саме
data-*: це штатний механізм HTML для додаткових даних на семантичному елементі, без нестандартних атрибутів і хаків. - Playwright — Test assertions — межа між , що автоматично повторюють перевірку, і тими, що ні: саме через неретрайні тест і стає флакі, бо сторінка показує дані асинхронно.
- Playwright — Test Isolation (browser contexts) — три названі наслідки ізоляції (немає перенесення падіння, легше дебажити, не треба думати про порядок) і дві стратегії: починати з нуля або прибирати між тестами.
- xUnit Test Patterns — Erratic Test — той самий підсаджений дефект під власною назвою:
Interacting Tests, корінь — спільна , маркер — тест зелений поодинці й червоний у . - xUnit Test Patterns — Fresh Fixture — свіжа фікстура на кожен тест запобігає нестабільним тестам.
- ISTQB® CTAL-TAE Syllabus v2.0 — §6.1: чому «перевірка без зрозумілого повідомлення» — дефект, а не дрібниця: у разі
failedрішення автоматизації має дати додаткову інформацію про причину.
- McDaniel, Roediger & McDermott (2007) — Generalizing test-enhanced learning from the laboratory to the classroom — чому тренування вголос працює: виграш дає саме пригадування, а не повторний перегляд матеріалу, і найсильніший ефект тест на відтворення дає разом із розбором помилок.
- Wikipedia — Testing effect — та сама рамка одним рядком: тест розглядають як інструмент навчання, а не оцінювання.
- Wikipedia — Spaced repetition — пригадування й рознесене повторення комбінуються для покращення довготривалої памʼяті; звідси «регулярно», а не «багато за раз».
Що таке лайвкодинг на співбесіді AQA і навіщо він, якщо є тестове завдання?
(live coding) — це коли ти пишеш код прямо на співбесіді, при інтерв'юері, який спостерігає за процесом у реальному часі: невелика функція, тест на живу сторінку або розбір чужого коду. Сенс саме в спостереженні: письмове показує лише кінцевий результат, а лайвкодинг відкриває шлях до нього. Інтерв'юер бачить те, що в готовому коді вже стерто, — як ти уточнюєш умову, звідки починаєш, коли згадуєш про . Тому це не заміна тестового, а інший зріз: не «що ти вмієш написати», а «як ти думаєш, коли пишеш».
Що насправді оцінюють на лайвкодингу, якщо не ідеальність коду?
Оцінюють процес мислення, а не бездоганність результату. Конкретно дивляться на чотири речі: декомпозицію (чи ділиш велику задачу на дрібні перевірні кроки), комунікацію (чи проговорюєш свої дії), реакцію на нову інформацію (підказку, уточнення, зміну вимог) та інженерну гігієну (edge cases, зрозумілі назви, самоперевірку перед «готово»). Ідеальний код — приємний бонус, але інтерв'юер уже бачив сотні реалізацій FizzBuzz, і його цікавить не відповідь. Через це буквально можлива ситуація, коли робочий, але мовчазний розв'язок отримує нижчий бал, ніж кривуватий, але добре проговорений.
Що інтерв'юер на лайвкодингу пробачає, а що — ні?
Пробачають технічні дрібниці: забутий синтаксис, переплутану назву методу, звертання до документації, перший неоптимальний підхід. Усе це нормально, бо в реальній роботі ти теж гуглиш сигнатуру й переписуєш перший варіант. Не пробачають натомість поведінкові речі: мовчання, відмову почати, код «на автопілоті» без жодної згадки про те, що може зламатися. Простими словами: помилка в коді — дрібниця, а от відсутність видимого мислення — це те, за що знижують бал.
Чому правильний, але мовчазний розв'язок може програти неідеальному, але проговореному?
Бо бал ставлять за мислення, яке інтерв'юер побачив, а не за те, що відбулося у тебе в голові. Якщо ти мовчки написав робочу функцію, для спостерігача це : він не знає, чи ти вивів логіку сам, чи згадав завчений шаблон, чи вгадав. А коли ти вголос перебираєш варіанти, називаєш edge cases й пояснюєш вибір, він бачить інженера в роботі — навіть якщо фінальний код з дрібним багом. Мовчазна досконалість не конвертується в бал, бо її нема як зарахувати.
Які три формати лайвкодингу бувають в AQA і чим вони відрізняються?
Під однією назвою ховаються три різні жанри. Перший — алгоритмічна задача: написати невелику функцію (реверс рядка, пошук дублікатів, retry-обгортка), тут дивляться на біглість у мові й edge cases. Другий — автотест наживо: написати або тест на реальну сторінку, тут перевіряють стратегію локаторів, очікування й структуру тесту. Третій — рев'ю коду: знайти проблеми в готовому шматку тесту, тут важливо, чи бачиш ти джерела й чи пояснюєш «чому». Готуватися до них треба по-різному, бо перевіряють вони різні навички.
Які алгоритмічні задачі типові саме для QA-лайвкодингу і чому не LeetCode?
Задачі прикладні, а не олімпіадні: динамічного програмування чи графів тут практично не буває. Натомість дають те, що ти робиш у тестовому коді щодня — операції над рядками (реверс, паліндром, частотний словник), над масивами (дублікати, унікальні, перетин), трансформації масиву об'єктів як (відфільтрувати, згрупувати, порахувати агрегат), асинхронні задачі (retry із , обмеження паралельності) та прості FizzBuzz-подібні на розгалуження. Причина проста: ці задачі дзеркалять реальну роботу автоматизатора, тоді як абстрактний LeetCode перевіряв би навичку, яку AQA майже не застосовує. Рівень очікувань росте з грейдом: від джуна чекають рядки й масиви, від мідла — впевнену роботу з масивами об'єктів і async.
Який правильний порядок дій, коли тобі дали алгоритмічну задачу?
Спершу уточнити, потім кодити — не навпаки. Погана послідовність: почути умову й одразу почати друкувати, бо так легко розв'язати не ту задачу. Добра: проговорити вголос відкриті питання (чи враховуємо регістр, який роздільник, що робити з порожнім вводом), навести приклад входу й очікуваного виходу, накидати наївне робоче рішення, прогнати його на edge cases і лише потім, якщо лишається час, оптимізувати. Наївний робочий варіант на цьому етапі цінніший за елегантний: спочатку «щоб працювало», краса — потім. Такий порядок показує інтерв'юеру системне мислення, а не рефлекс друкувати.
До тебе відкрили живу сторінку й просять написати локатор. З чого почати і на що дивляться?
Дивляться на інженерну зрілість автоматизатора, а не на алгоритми. Перед кодом варто уточнити контекст: який браузер, чи є на елементах 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). Тобто перевіряють, чи бачиш ти проблему системно, а не за списком «поганих слів».
Навіщо проговорювати думки вголос і як це робити правильно?
Проговорювання — це головна мета-навичка, заради якої весь етап існує, бо воно робить твоє мислення видимим. Правило просте: кажи, що збираєшся зробити, перед тим як це зробити. Наприклад: «спершу уточню, чи рядок може бути порожнім і чи рахуємо юнікод окремими символами; далі пройдуся по символах і складатиму словник частот». Так інтерв'юер чує хід думки, і навіть якщо ти застрягнеш на синтаксисі, він уже бачить, що логіку ти тримаєш. Тиша ж лишає його наодинці з порожнім екраном, де нема що оцінювати.
Які edge cases треба називати самому і чому це перевага QA-кандидата?
Називати варто повний типовий набір, не чекаючи підказки: порожній ввід, null/undefined, дуже великий ввід, дублікати, юнікод і пробіли, від'ємні числа, а для асинхронних задач — , помилку й порожній список. Робити це треба вголос, у момент постановки задачі, а не коли інтерв'юер сам про них спитає. Саме тут тестувальник має структурну перевагу над кандидатом-розробником: думати про те, що зламається, — його основна професійна навичка, тому пропустити edge cases для AQA гірше, ніж для програміста. Названі вголос edge cases — один із найсильніших сигналів, що перед інтерв'юером саме QA-інженер.
Інтерв'юер дав підказку. Як на неї реагувати?
Підказка — це сигнал і допомога, а не вирок і не «ти провалився». Її дають, щоб зрушити тебе з місця й побачити, чи вмієш ти вбудувати нову інформацію — рівно так, як вбудовуватимеш коментарі рев'юера в реальній роботі. Правильна реакція — вдячно взяти й одразу застосувати: «дякую, тобто замість вкладеного циклу тут краще Map за один прохід — так, це прибирає квадратичну складність». Погана — проігнорувати підказку й уперто йти своїм шляхом або розгубитися й замовкнути. Уміння прийняти підказку читається як «з цим кандидатом легко працювати в парі», а оборона від неї — як «кожне рев'ю буде боєм».
Ти застряг посеред задачі. Що робити?
Застрягнути — нормально, на це дивляться не менш уважно, ніж на гладкий розв'язок, бо в роботі ти теж застрягатимеш. Єдина справжня помилка — застрягнути мовчки. Порядок дій такий: проговори, де саме затик («знаю, що треба згрупувати за статусом, але не пригадаю синтаксис reduce»); спрости задачу до меншої версії (спершу просто відфільтруй один статус); напиши наївне робоче рішення, хай навіть на подвійному циклі, бо робоче O(n²) б'є елегантне неробоче; якщо реально глухо — прямо попроси підказку; і прожени те, що вже написав, на прикладі замість тупцювати на місці. Мовчазні п'ять хвилин у стелю коштують дорожче за чесне «я застряг ось тут».
Як тренуватися до лайвкодингу, щоб не завалити його від хвилювання?
Тиша на реальній співбесіді частіше йде від нетренованості говорити й кодити одночасно, ніж від незнання, тому тренувати треба саме цю пару навичок. Розв'язуй задачі вголос або записуючи себе на диктофон, щоб проговорювання стало звичкою. Доведи до автоматизму базову «мову»: методи масивів (map/filter/reduce/find), Promise.all/allSettled, async/await мають згадуватися без гуглінгу елементарного. Тренуйся в тому середовищі, де проситимуть, — часто це середовище бідніше за звичну IDE (онлайн-редактор на кшталт CoderPad, спільний документ), тож порепетируй без милиць. І додай -співбесіди з таймером, бо штучний тиск часу — окрема навичка, а ще навчись пояснювати кожне рішення у власному фреймворку, бо багато AQA-лайвкодингів — це «покажи, як ти пишеш тест» на твоєму ж стеку.
Які типові помилки на лайвкодингу і чому кожна виглядає не тим, чим є?
Найпоширеніші п'ять. «Мовчазний геній» виглядає як зосередженість, а насправді ховає мислення й тягне бал вниз. «Кинувся кодити одразу» виглядає як упевненість, а насправді пропускає уточнення й веде до розв'язання не тієї задачі. Ігнорування edge cases виглядає як «основне ж працює», а для 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. Таблиця сигналів: як поведінка кандидата читається в бал
Інтерв'юер оцінює не тільки код, а й серію мікросигналів. Ось як типові з них конвертуються в оцінку — корисно тримати перед очима, коли готуєшся.
| Поведінка кандидата | Як читає інтерв'юер | Куди тягне бал |
|---|---|---|
| Уточнив умову й навів приклад входу/виходу до коду | Системне мислення, не розв'язує не ту задачу | Вгору |
| Назвав edge cases сам, без підказки | Профільний QA-рефлекс | Вгору |
| Вдячно взяв підказку й одразу застосував | Легко працювати в парі | Вгору |
| Чесно сказав «застряг ось тут, гляну в доку» | Самоусвідомлення, а не блеф | Вгору |
| Мовчки написав робочий код | Black-box, мислення не видно | Вниз |
| Кинувся друкувати одразу після умови | Пропустив уточнення, ризик не тієї задачі | Вниз |
| Проігнорував або відкинув підказку | Складний у парній роботі | Вниз |
| Хвилини мовчання в затику | Не видно, де саме проблема | Вниз |
| Одразу шукає «найкращий алгоритм» замість робочого | Передчасна оптимізація, з'їдає час | Вниз |
Головний висновок таблиці: майже кожен «мінусовий» рядок виглядає ззовні як щось хороше — упевненість, принциповість, зосередженість, сеньйорність. Пастка саме в цьому, тому на тренуванні варто ловити себе не на помилках у коді, а на цих оманливих на вигляд патернах поведінки.
Що перевіряє лайвкодинг
- Розумію, що оцінюють процес мислення, а не бездоганність коду, і можу пояснити чотири осі: декомпозиція, комунікація, реакція на нову інформацію, інженерна гігієна.
- Можу сформулювати, чому існує поряд із : тестове показує результат, лайвкодинг — шлях до нього.
- Знаю, що інтерв'юер пробачає (забутий синтаксис, звертання до доки, перший неоптимальний підхід) і чого не пробачає (мовчання, відмову почати, код без думки про ).
- Розумію контрінтуїтивне: робочий, але мовчазний розв'язок може отримати нижчий бал, ніж кривуватий, але проговорений.
Три формати
- Розрізняю три жанри лайвкодингу — алгоритмічна задача, автотест наживо, рев'ю коду — і знаю, що кожен перевіряє інші навички.
- Знаю, що 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 і порушену ізоляцію стану між тестами. - Розумію, що оцінюють не «тицьнув, що погано», а пояснення «чому» плюс конкретний фікс.
Мислення вголос і edge cases
- Тримаю правило: кажу, що збираюся зробити, перед тим як це зробити.
- Знаю базовий чек-ліст edge cases, який називаю сам (порожній ввід,
null/undefined, великий ввід, дублікати, юнікод і пробіли, від'ємні числа, а для async — , помилка, порожній список), і чому названі вголос edge cases — головна перевага QA над кандидатом-розробником. - Пам'ятаю порядок: уточнити → приклад входу/виходу → наївне робоче рішення → прогнати edge cases → лише потім оптимізувати.
Підказки, застрягання, підготовка
- Розумію, що підказка — це допомога й позитивний сигнал; беру її вдячно й одразу застосовую, а не обороняюся.
- Знаю алгоритм при застряганні: проговори затик → спрости до меншого випадку → напиши наївний робочий варіант → попроси підказку прямо → перевір на прикладі; мовчати не можна.
- Пам'ятаю, що робоче
O(n²)б'є елегантне неробоче, і можу перелічити типові фейли (кожен оманливий на вигляд): мовчазний геній, кинувся кодити одразу, ігнор edge cases, оборона від підказки, передчасна оптимізація. - Знаю, як тренуватись: вголос/на диктофон, базова «мова» без гуглінгу, «голий» редактор без IDE, -співбесіди з таймером, розбір власного фреймворку.
Квіз
Перед стартом
- Питань: 14
- Поріг «зараховано»: ≥70% правильних відповідей.
- Результат впливає на прогрес; завалені питання підуть у чергу повторення.
- Квіз впливає на компліт теми: тема стає «пройдено», лише коли прочитано теорію І квіз складено на ≥70%.
Питання
Що таке лайвкодинг (live coding) на співбесіді AQA?