Промптинг для QA
Зміст
Одна й та сама модель на запит «напиши тести для форми логіну» видасть банальний список із п'яти пунктів, а на добре зібраний промпт — структуровану сюїту з негативними перевірками, крайовими значеннями й прив'язкою до технік тест-дизайну. Модель не змінилася між цими двома запитами. Змінився промпт. Промптинг (prompting) — це навичка формулювати завдання так, щоб дістати корисний результат, і для QA вона перетворилася на робочий інструмент: генерація тест-кейсів, тестових даних, аналіз вимог, розбір падінь, чернетки автотестів.
Промпт варто читати не як «запит у чат», а як технічне завдання виконавцю, який нічого не знає про ваш проєкт. Виконавець швидкий, ерудований і слухняний, але без контексту він домислює, а домисли LLM — це часто впевнено сформульована вигадка. Тому питання на співбесідах уже не «чи користуєтесь AI», а «покажіть промпт, яким ви генеруєте тест-кейси, і поясніть, чому він саме такий». Ця глава — про те, з чого промпт складається і які важелі реально впливають на якість виводу. Механіку того, чому модель узагалі реагує на приклади й формулювання, розібрано в главі «Як працюють LLM».
Анатомія промпта
Сильний промпт майже завжди має впізнавану структуру. Це не бюрократія — кожен блок закриває конкретний спосіб, яким модель може «промахнутися».
- Роль і контекст — хто модель у цій задачі й що вона має знати про проєкт: стек, домен, конвенції. Модель не знає, що у вас Playwright на TypeScript і що severity ви ставите за вашою внутрішньою шкалою, доки ви не скажете.
- Задача — одна чітка ціль, сформульована дієсловом: «згенеруй», «проаналізуй», «знайди суперечності». Дві незалежні задачі в одному промпті — привід розбити на два.
- Вхідні дані — вимога, user story, шматок коду, лог. Їх варто відокремлювати від інструкцій — трьома бектиками або тегами-обгортками (
<requirements>...</requirements>), щоб модель не сплутала дані з командами. Це заодно перший бар'єр проти prompt injection (див. нижче). - Обмеження й правила — що робити не можна: не вигадувати селектори, спиратися лише на надані вимоги, покрити класи еквівалентності й межі, не дублювати кейси.
- Формат виводу — таблиця, JSON, Gherkin, Markdown-чеклист. Без цього модель обере формат сама, і він рідко збігається з тим, що ви очікуєте імпортувати в TMS.
- Приклади — один-два зразки «вхід → бажаний вихід». Найсильніший важіль форми й стилю (про це — далі).
Не кожна задача потребує всіх шести блоків. Але коли вивід розчаровує, діагностика починається саме з цього списку: якого блоку бракує? Порожній результат майже завжди означає, що бракує вхідних даних або критеріїв «що вважати хорошим кейсом».
Zero-shot і few-shot
Zero-shot — це промпт без прикладів: ви просто описуєте задачу. Для поширених речей (пояснити статус-код, накидати очевидні перевірки) цього достатньо, бо схожі приклади модель бачила під час навчання мільйони разів.
Few-shot — це промпт, у який ви вклали кілька зразків «вхід → вихід». Модель підхоплює патерн: формат, рівень деталізації, стиль назв, тон. Термін закріпився за статтею про GPT-3 «Language Models are Few-Shot Learners» — модель навчається патерну прямо з прикладів у промпті, без донавчання ваг (це називають in-context learning). One-shot — окремий випадок з одним прикладом.
Чому це працює саме для QA. LLM продовжує патерн, а не «розуміє інструкцію» в людському сенсі. Тому одне речення «пиши в нашому форматі» слабше за один показаний зразок цього формату. Якщо у вас є house-стиль баг-репортів або конвенція назв тест-кейсів (назва описує перевірку, а не дію) — покажіть один готовий приклад, і решта згенерується під нього.
Формат тест-кейсу — як у прикладі нижче.
Приклад:
Вхід: Поле "Email" обов'язкове.
Вихід:
- Назва: Форма відхиляє відправлення з порожнім email
Кроки: 1) лишити email порожнім 2) натиснути "Зареєструватися"
Очікуваний результат: помилка валідації, форма не відправлена
Тепер згенеруй кейси для вимоги:
Вхід: Пароль — від 8 до 64 символів.
Практичне правило: починайте із zero-shot; щойно вивід «майже той, але не в тому форматі / не тієї деталізації» — додайте один-два приклади, і форма вирівняється. Два-три приклади зазвичай дають більший приріст, ніж сторінка словесних інструкцій про формат.
Chain-of-thought: міркування вголос
Chain-of-thought (CoT, ланцюжок міркувань) — це прийом, коли ви просите модель спершу міркувати покроково, а вже потім давати відповідь. Ідею описано у статті Wei та ін. (2022): для задач із кількома логічними кроками проміжні міркування помітно підвищують якість відповіді, бо модель «розкладає» задачу, а не намагається вгадати підсумок одразу.
Для QA це природно лягає на декомпозицію. Замість «згенеруй тести для поля віку» — «спершу визнач класи еквівалентності, потім граничні значення для кожного класу, потім склади з них тест-кейси». Модель проходить ті самі кроки, що й тестувальник, і рідше пропускає межу.
Два важливі уточнення, які й перевіряють на співбесіді:
- Сучасні моделі з режимом міркування (reasoning) роблять цей крок усередині, тож явне «think step by step» їм потрібне рідше. Але структурувати саму задачу на етапи все одно корисно — це різні речі.
- Текст міркувань — це правдоподібне пояснення, а не доказ правильності. Модель може написати логічний ланцюжок і все одно дійти хибного висновку (або, навпаки, дати правильну відповідь із кривим поясненням). CoT покращує середню якість, але не звільняє від перевірки — див. главу «Верифікація результатів AI».
Роль і персона
Призначення ролі — «ти досвідчений QA-інженер, який спеціалізується на API-тестуванні» — зміщує словник і рамку відповіді: модель частіше говорить про статус-коди, схеми, ідемпотентність, а не загальними словами. Це справжній, але обмежений важіль.
Чого роль не робить: вона не додає моделі знань, яких у неї немає, і не робить вивід достовірним. «Ти найкращий у світі тестувальник» не покращує нічого — це порожній комплімент. Сучасні моделі загалом менш чутливі до пафосних персон, ніж ранні; точний опис задачі й контексту працює сильніше за титул. Роль корисна, коли задає перспективу («подивись на цю форму очима зловмисника», «оціни як рев'ювер PR»), а не коли просто роздає регалії.
Структурований вивід
QA рідко потрібен «текст для читання» — частіше вивід кудись їде далі: імпорт у TMS, вставка в код, крок у пайплайні. Тому формат треба задавати явно: таблиця з фіксованими колонками, Markdown-чеклист, Gherkin, JSON із конкретними полями.
Є два рівні контролю формату:
- Проханням у промпті — «поверни JSON-масив об'єктів із полями
title,steps,expected». Просто, працює для більшості задач, але модель може порушити формат на довгому виводі (загубити кому, додати пояснення до JSON). - Гарантованою схемою на рівні API — structured output / function calling, де модель зобов'язана віддати вивід за JSON-схемою. Це надійніше для інтеграцій; механіку розбираємо в главі «Tool use і function calling».
Ключове правило: навіть заданий формат треба валідувати. Не «довіряй, що JSON валідний», а розпарси й перевір поля — інакше зламаний вивід тихо потрапить у пайплайн.
// Мінімальна валідація структурованого виводу перед використанням
type TestCase = { title: string; steps: string[]; expected: string };
function parseTestCases(raw: string): TestCase[] {
const data = JSON.parse(raw); // кине помилку на битому JSON — і добре
if (!Array.isArray(data)) throw new Error("Очікувався масив кейсів");
for (const tc of data) {
if (!tc.title || !Array.isArray(tc.steps) || !tc.expected) {
throw new Error(`Неповний кейс: ${JSON.stringify(tc)}`);
}
}
return data;
}
Ітеративне уточнення
Промптинг — це діалог, а не постріл наосліп. Рідко коли перший промпт дає ідеальний результат; нормальний робочий цикл — отримати чернетку, вказати на конкретну ваду, попросити доробити.
Уточнення працює краще, коли воно адресне: не «зроби краще», а «додай перевірки на порожні значення й unicode», «ти пропустив верхню межу 64 символи», «прибери дубль кейсів 3 і 5». Корисний окремий хід — попросити модель самокритику: «які сценарії ти не покрив?».
Дві пастки ітерації. По-перше, контекст накопичується, і після десятка правок модель починає «дрейфувати» — тягнути старі рішення. Іноді дешевше не воювати правками, а переписати промпт з нуля, вклавши в нього все, чого навчився діалог. По-друге, довгий брудний контекст сам по собі знижує якість — про деградацію на довгому вікні див. главу «Токени, контекст і вартість».
І головне: вдалий промпт — це артефакт. Формат кейсів, правила, приклади, які спрацювали, варто зберегти й перевикористовувати, а не вигадувати щоразу. Як зафіксувати такі правила на рівні проєкту (файли на кшталт CLAUDE.md, скіли, слеш-команди) — тема глави «Пам'ять, скіли та слеш-команди».
Промпти для типових QA-задач
Складаючи докупи все вище, ось патерни, які покривають більшість щоденних задач. Глибоко генерацію артефактів розбирає окрема глава «Генерація тест-артефактів» — тут лише каркас промптів.
- Тест-кейси з вимоги — вхід: текст вимоги (відокремлений); правила: покрити класи еквівалентності, межі, негативні сценарії; формат: таблиця чи JSON; приклад одного кейсу для стилю.
- Тестові дані — «згенеруй крайові й невалідні значення для поля X»: порожнє, пробіли, максимальна довжина, unicode, спецсимволи, ін'єкційні payload як smoke. Техніки тест-дизайну (класи еквівалентності, граничні значення) — окремий розділ теорії, на них варто прямо посилатися в промпті.
- Аналіз вимог — «знайди суперечності, прогалини й неоднозначності в цій user story; що треба уточнити в аналітика?». Тут CoT особливо корисний.
- Розбір падіння — вхід: лог/трейс/повідомлення помилки; задача: назвати ймовірну причину й де копати. Пам'ятайте, що модель дає гіпотезу, а не діагноз.
- Локатор чи сніпет — «дай стабільний Playwright-локатор для цієї кнопки за наданим HTML; пріоритет getByRole/getByTestId». Обов'язково перевіряйте: модель охоче вигадує селектори, яких у розмітці немає.
Компактний шаблон сильного QA-промпта:
Роль: senior QA, стек Playwright + TypeScript.
Задача: згенерувати тест-кейси для вимоги нижче.
Вимога:
<requirements>
Пароль: 8–64 символи, мінімум одна цифра.
</requirements>
Правила: покрий класи еквівалентності та граничні значення;
додай негативні сценарії; спирайся лише на вимогу, не вигадуй полів.
Формат: JSON-масив об'єктів {title, steps, expected}.
Типові помилки
- Виглядає як «модель лінива», а насправді — бракує вхідних даних. Порожній чи банальний вивід на «напиши тести» — це не впертість моделі, а відсутність вимоги, контексту й критеріїв. Виконавцю не дали ТЗ.
- Виглядає як промптинг, а насправді — роздача титулів. «Ти геніальний тестувальник» замість конкретної інструкції нічого не додає. Персона задає перспективу, а не знання.
- Звучить упевнено — отже, правда. Ні. Модель однаково впевнено формулює і факт, і галюцинацію (вигаданий метод, неіснуючий селектор, вигадану вимогу). Впевнений тон — не сигнал достовірності.
- CoT написав логічний ланцюжок — отже, відповідь правильна. Міркування — це раціоналізація, а не доказ. Перевіряти треба висновок, а не милуватися ходом думки.
- Один гігантський промпт «на все». Три задачі, суперечливі правила й мегапортянка контексту в одному запиті — модель губиться й на довжині, і на конфлікті інструкцій. Дробіть.
- Попросив формат — і довірився. Заданий JSON ≠ валідний JSON. Без розбору й перевірки полів зламаний вивід тихо просочиться далі.
- Вставив неперевірений текст у промпт. Лог, тікет чи сторінка, які ви кладете у промпт як дані, можуть містити інструкції для моделі (prompt injection). Тому дані відокремлюють від інструкцій; ризик докладно — у главі «Безпека й приватність при роботі з AI».
Підсумок
- Промпт — це ТЗ для виконавця без контексту; якість виводу впирається в якість промпта, а не в «настрій» моделі.
- Приклади (few-shot) — найсильніший важіль форми й стилю: один показаний зразок б'є абзац словесних вимог.
- Chain-of-thought підвищує якість на багатокрокових задачах, але міркування — не гарантія правильності; висновок усе одно перевіряють.
- Вхідні дані відокремлюють від інструкцій, вивід задають форматом і валідують, а не приймають на віру.
- Промптинг ітеративний: адресні правки, а не «зроби краще»; вдалий промпт зберігають як багаторазовий артефакт.
Що питають на співбесіді
- «Покажіть промпт, яким ви генеруєте тест-кейси». Інтерв'юер дивиться, чи є в промпті структура: контекст, відокремлені вхідні дані, правила (техніки тест-дизайну!), формат виводу, приклад. Промпт «напиши тести» — червоний прапорець.
- «Чим few-shot відрізняється від zero-shot і коли що?» Хочуть почути, що приклади задають патерн формату/стилю, і що починають зазвичай із zero-shot, а приклади додають, коли треба вирівняти форму.
- «Що таке chain-of-thought і чи гарантує він правильність?» Правильна відповідь — покрокове міркування допомагає на складних задачах, але це не доказ; результат перевіряють окремо.
- «Модель дала впевнену відповідь — ви їй довіряєте?» Перевірка на зрілість: впевнений тон не корелює з достовірністю; галюцинації звучать так само переконливо.
- «Як ви контролюєте, щоб вивід був у потрібному форматі?» Очікують: задаю формат явно (краще — схемою), і обов'язково валідую результат перед використанням.
Джерела
- Brown та ін. «Language Models are Few-Shot Learners» (2020) — arxiv.org/abs/2005.14165. Канонічне джерело few-shot-промптингу та in-context learning для LLM.
- Wei та ін. «Chain-of-Thought Prompting Elicits Reasoning in Large Language Models» (2022) — arxiv.org/abs/2201.11903.
- Anthropic, Prompt engineering — docs.anthropic.com.
- OpenAI, Prompt engineering guide — platform.openai.com/docs/guides/prompt-engineering.
- ISTQB Certified Tester AI Testing (CT-AI) — istqb.org — суміжний силабус про тестування AI-систем (не про промптинг як такий); CTFL 4.0 промптингу не покриває.
Що таке промптинг і чому для QA це вже робоча навичка, а не забавка?
Промптинг (prompting) — це вміння сформулювати задачу для мовної моделі так, щоб дістати придатний до роботи результат, а не банальний першоряд. Одна модель на кульгаве «напиши тести» і на зібране технічне завдання відповість зовсім по-різному, хоча самі ваги між запитами не змінюються — змінюється лише промпт. Для тестувальника це щоденний інструмент: чернетки тест-кейсів, генерація крайових даних, вичитка вимог на суперечності, перша гіпотеза щодо падіння. Тому й на співбесіді питають уже не «чи користуєтесь AI», а «покажіть свій промпт для тест-кейсів і поясніть, чому він саме такий».
З яких частин складається добре зібраний промпт?
Сильний промпт має впізнавану структуру, де кожен блок закриває окремий спосіб промахнутися. Зазвичай це шість елементів: роль і контекст (хто модель у задачі, який стек і домен), сама задача одним дієсловом, вхідні дані, відокремлені від інструкцій, обмеження й правила («спирайся лише на вимогу», «покрий межі»), явний формат виводу і приклади бажаного результату. Не кожна задача потребує всіх шести, але коли вивід розчаровує, діагностика починається саме з питання «якого блоку бракує?». Порожній або надто загальний результат майже завжди означає, що моделі не дали ані вхідних даних, ані критеріїв «що вважати хорошим кейсом».
Чому вхідні дані у промпті варто відокремлювати від інструкцій?
Модель не має надійного вбудованого поділу на «команду» й «матеріал» — усе, що ви їй передали, для неї суцільний текст. Якщо вимогу, лог чи шматок тікета вклеїти прямо в тіло інструкції, модель може сплутати рядок усередині даних із командою собі. Тому дані обгортають — трьома бектиками або тегами на кшталт <requirements>...</requirements> — щоб чітко провести межу «ось тут завдання, а ось тут матеріал для нього». Це заодно перший бар'єр проти ін'єкції в промпт (prompt injection), коли у вставленому тексті ховається директива для моделі. Для QA це базова гігієна: будь-який зовнішній текст у промпті — це дані, а не наказ.
Чим zero-shot відрізняється від few-shot і з чого починати?
Zero-shot — це промпт без прикладів: ви просто описуєте задачу словами. Для типового (пояснити статус-код, накидати очевидні перевірки) цього достатньо, бо подібне модель бачила під час навчання безліч разів. Few-shot — це промпт із кількома зразками «вхід → бажаний вихід», з яких модель підхоплює патерн: формат, глибину деталізації, стиль назв, тон. Практичне правило — стартувати із zero-shot, а щойно вивід «майже той, але не в тому форматі», додати один-два приклади, і форма вирівняється. Кілька показаних зразків зазвичай дають більший приріст, ніж ціла сторінка словесних вимог до формату.
Що таке in-context learning і при чому тут few-shot?
In-context learning — це коли модель ловить потрібний патерн прямо з прикладів усередині промпта, не змінюючи власних ваг, тобто без жодного донавчання. Термін закріпився за роботою про GPT-3 «Language Models are Few-Shot Learners»: модель наче «вчиться» на льоту з того, що ви поклали в контекст. Механізм пояснює, чому для QA один показаний зразок house-стилю б'є абзац його опису: модель продовжує явний патерн надійніше, ніж виконує абстрактну вказівку. One-shot — окремий випадок з єдиним прикладом. Для практики висновок простий: маєте конвенцію назв кейсів чи формат баг-репорту — покажіть готовий приклад, а не описуйте його на словах.
Що таке chain-of-thought і чи гарантує він правильну відповідь?
Chain-of-thought (CoT, ланцюжок міркувань) — це прийом, коли модель просять спершу міркувати покроково, а вже потім давати підсумок; на багатокрокових задачах проміжні кроки помітно піднімають якість. Але тут ховається головна пастка, яку й перевіряють на співбесіді: текст міркувань — це правдоподібне пояснення, а не доказ правильності. Модель може виписати струнку логіку й усе одно дійти хибного висновку, або навпаки — дати вірну відповідь із кривим обґрунтуванням. Тобто CoT покращує середню якість, але не звільняє від перевірки. Перевіряти треба висновок, а не милуватися ходом думки.
Сучасним reasoning-моделям ще потрібне «think step by step»?
Здебільшого ні — моделі з режимом міркування (reasoning) виконують цей крок усередині, тож явна вказівка «думай покроково» їм потрібна рідше, ніж раннім моделям. Але це не скасовує користі від того, щоб структурувати саму задачу на етапи: «спершу класи еквівалентності, потім межі кожного класу, потім кейси» — це вже про декомпозицію завдання, а не про вмикання міркувань. Ці дві речі легко сплутати, і сильний кандидат їх розділяє: одне — просити модель міркувати, інше — самому розкласти задачу на кроки. Друге корисне завжди, бо змушує модель пройти той самий шлях, що й тестувальник, і рідше пропустити межу.
Що дає моделі призначення ролі, а чого не дає?
Роль на кшталт «ти QA-інженер зі спеціалізацією на API» зміщує словник і рамку відповіді: модель частіше говорить про статус-коди, схеми, ідемпотентність, а не загальниками. Це реальний важіль, але обмежений. Чого роль не робить: вона не додає моделі знань, яких у неї немає, і не робить вивід достовірним. Роль працює найкраще, коли задає перспективу — «подивись на цю форму очима зловмисника», «оціни як рев'ювер PR», — а не коли просто роздає титули. Тобто цінність ролі в куті зору, під яким модель дивиться на задачу, а не в регаліях.
Чому «ти геніальний тестувальник світу» нічого не покращує?
Бо це порожній комплімент, а не інструкція: він не додає ані знань, ані контексту, ані критеріїв якості. Сучасні моделі загалом менш чутливі до пафосних персон, ніж ранні, і точний опис задачі та стеку працює сильніше за будь-який титул. Плутанина «роздав регалії — отже, зайнявся промптингом» — типова помилка, яку легко спіймати на співбесіді. Замість «ти найкращий» дайте конкретику: стек, вимогу, правила покриття, формат виводу, приклад. Роль корисна як перспектива, а не як похвала.
Як контролювати формат виводу і навіщо його валідувати?
QA рідко потрібен «текст для читання» — вивід зазвичай їде далі: імпорт у TMS, вставка в код, крок у пайплайні. Тому формат задають явно: таблиця з фіксованими колонками, Markdown-чеклист, Gherkin, JSON із конкретними полями. Але навіть заданий формат не можна приймати на віру: на довгому виводі модель здатна загубити кому чи дописати пояснення до JSON. Тому результат треба розпарсити й перевірити поля програмно, а не «довіритися, що JSON валідний». Інакше зламаний вивід тихо просочиться далі по пайплайну й спливе вже там, де ловити його дорого.
Чим прохання формату в промпті відрізняється від гарантованої схеми на рівні API?
Це два рівні контролю. Перший — просто попросити в промпті: «поверни JSON-масив об'єктів із полями title, steps, expected». Просто й працює для більшості задач, але формат тримається на добрій волі моделі й може зламатися на довгому виводі. Другий — гарантована схема через structured output або function calling, де модель зобов'язана віддати результат за заданою JSON-схемою на рівні API. Це надійніше для інтеграцій, бо структуру гарантує вже не текст промпта, а контракт. Але навіть тут семантику (чи всі поля осмислені, чи не порожні кроки) все одно варто перевірити своїм кодом.
Модель відповіла впевнено. Ви їй довіряєте?
Ні — упевнений тон не корелює з достовірністю. Модель однаково переконливо формулює і факт, і галюцинацію: вигаданий метод, неіснуючий селектор, вимогу, якої в тексті не було. Це перевірка на зрілість: сильний кандидат знає, що галюцинації звучать так само гладко, як правда, тому сигналом істинності тон бути не може. Практичний наслідок — усе, що модель стверджує про код, API чи розмітку, треба звірити з першоджерелом. Особливо це стосується локаторів: модель охоче вигадує селектори, яких у наданому HTML немає.
Як виглядає нормальний цикл ітеративного уточнення промпта?
Промптинг — це діалог, а не постріл наосліп: перший промпт рідко дає ідеал, тож нормально отримати чернетку, вказати на конкретну ваду й попросити доробити. Ключ у тому, щоб правки були адресні: не «зроби краще», а «додай перевірки на порожні значення й unicode», «ти пропустив верхню межу 64 символи», «прибери дубль кейсів 3 і 5». Корисний окремий хід — попросити модель самокритику: «які сценарії ти не покрив?». Розмите «покращ» модель трактує як завгодно, а точна вказівка дає передбачуваний результат.
Коли дешевше переписати промпт з нуля, ніж правити далі?
Коли контекст діалогу забруднився й модель починає «дрейфувати» — тягнути старі рішення попри нові вказівки. Після десятка правок накопичена історія сама по собі тисне на вивід, і кожна нова правка воює з попередніми. У такий момент вигідніше не боротися латками, а зібрати новий чистий промпт, вклавши в нього все, чого навчив діалог: робочий формат, правила, вдалі приклади. Додатковий аргумент — довгий брудний контекст ще й знижує якість сам собою, бо на розтягнутому вікні модель гірше тримає деталі. Тобто перепис — це не поразка, а спосіб зафіксувати здобуте й скинути шум.
Чому вдалий промпт варто зберігати як артефакт?
Бо робочий промпт — це не одноразова репліка, а багаторазовий інструмент: формат кейсів, правила покриття, приклади, які вже спрацювали, не варто вигадувати щоразу заново. Збережений промпт дає стабільність (уся команда генерує в одному стилі) і економить час на кожній наступній задачі того ж класу. На рівні проєкту такі правила фіксують у файлах на кшталт CLAUDE.md, у скілах чи слеш-командах, щоб контекст підтягувався автоматично. Тобто зрілий промптинг — це поступове нарощування бібліотеки перевірених промптів, а не постійна імпровізація з нуля.
Чому промпт «напиши тести для форми логіну» — червоний прапорець на співбесіді?
Бо в ньому немає нічого, крім задачі: ані вхідних вимог, ані контексту стеку, ані правил покриття, ані формату, ані прикладу. Порожній чи банальний вивід на такий запит — це не лінь моделі, а відсутність технічного завдання: виконавцю просто не дали, з чого працювати й що вважати хорошим результатом. Інтерв'юер саме й дивиться, чи розуміє кандидат, що якість виводу впирається в якість промпта. Сильна відповідь показує структуру: відокремлена вимога, правила з техніками тест-дизайну (класи еквівалентності, межі, негативні сценарії), явний формат і зразок одного кейсу для стилю.
Три кейси з робочого дня QA, де вивід моделі вирішує промпт, а не «настрій» моделі: перепис слабкого запиту в структуроване ТЗ із діагностикою по блоках, вирівнювання house-стилю назв через один приклад (few-shot), і валідація структурованого JSON перед тим, як пустити його в пайплайн. Скрізь — що дивитися і чому.
Кейс 1. Слабкий промпт проти сильного: діагностика по блоках
На вимогу «Пароль: 8–64 символи, мінімум одна цифра» тестувальник кидає в модель:
Напиши тести для пароля.
Вивід — п'ять банальних рядків: «валідний пароль», «короткий пароль», «довгий пароль», «без цифри», «порожній». Ні меж, ні unicode, ні формату для імпорту. Це не лінь моделі — їй просто не дали технічного завдання. Пройдімося по блоках і побачимо, чого бракує:
| Блок промпта | Що було | Наслідок у виводі |
|---|---|---|
| Роль і контекст | немає | загальні кейси, не прив'язані до стеку |
| Вхідні дані | вклеєні в задачу, без меж | модель домислює правила пароля |
| Обмеження й правила | немає | ні класів еквівалентності, ні меж 7/8/64/65 |
| Формат виводу | немає | плаский список, не імпортувати в TMS |
| Приклад | немає | випадковий стиль назв і кроків |
Той самий запит, зібраний як ТЗ:
Роль: senior QA, стек Playwright + TypeScript.
Задача: згенерувати тест-кейси для вимоги нижче.
Вимога:
<requirements>
Пароль: 8–64 символи, мінімум одна цифра.
</requirements>
Правила: покрий класи еквівалентності та граничні значення (7, 8, 64, 65);
додай негативні сценарії; спирайся лише на вимогу, не вигадуй полів.
Формат: JSON-масив об'єктів з полями title, steps, expected.
Що дивитися і чому:
- Вимога відокремлена тегами
<requirements>. Модель тепер не сплутає текст вимоги з інструкцією, а ви дістали перший бар'єр проти ін'єкції, якщо вимога прийшла з чужого тікета. - Правила прямо називають техніки тест-дизайну. Без слів «класи еквівалентності та межі» модель не зобов'язана перевіряти саме 7/8 і 64/65 — а це і є та межа, яку найчастіше пропускають.
- «Спирайся лише на вимогу» гасить фантазію. Інакше модель дофантазовує правила (спецсимволи, великі літери), яких у вимозі немає, і ви отримаєте кейси на неіснуючі обмеження.
- Формат заданий явно. JSON із фіксованими полями можна одразу парсити й імпортувати; без цього рядка модель обере форму сама, і вона рідко збіжиться з очікуваною.
Кейс 2. Few-shot: вирівняти house-стиль назв одним прикладом
У команди конвенція: назва тест-кейсу описує інваріант, що перевіряється, а не дію («Форма відхиляє відправлення з порожнім email»), а не «Ввести порожній email». Zero-shot цього не знає й видає назви-дії:
Згенеруй тест-кейси для вимоги: поле "Email" обов'язкове.
1. Перевірити відправлення з порожнім email
2. Ввести валідний email і надіслати
Назви-дії — не наш стиль. Замість абзацу пояснень показуємо один зразок і даємо модели підхопити патерн (few-shot):
Формат назви кейсу — рівно як у прикладі.
Приклад:
Вхід: Поле "Email" обов'язкове.
Вихід:
- Назва: Форма відхиляє відправлення з порожнім email
Кроки: 1) лишити email порожнім 2) натиснути "Зареєструватися"
Очікуваний результат: помилка валідації, форма не відправлена
Тепер згенеруй кейси для вимоги:
Вхід: Пароль — від 8 до 64 символів.
Що дивитися і чому:
- Один приклад б'є сторінку інструкцій. Модель продовжує показаний патерн (назва = перевірка, а не дія) надійніше, ніж виконує абстрактну вказівку «пиши в нашому стилі» — це прямий наслідок in-context learning.
- Приклад задає одразу три речі: назву, глибину кроків і формулювання результату. Тобто вирівнюється не лише заголовок, а вся структура кейсу.
- Правило застосування. Стартуйте із zero-shot; щойно вивід «майже той, але не в тому стилі» — додайте один-два приклади. Кидати приклади наперед у прості задачі не варто, це лише роздуває промпт.
Кейс 3. Валідація структурованого виводу перед пайплайном
Модель повернула JSON-масив тест-кейсів, і спокуса — одразу згодувати його імпортеру. Але «попросив формат» ще не означає «формат валідний»: на довгому виводі модель здатна загубити поле чи дописати текст поза JSON. Тому перед використанням вивід парсять і перевіряють поля.
import { test, expect } from '@playwright/test';
type TestCase = { title: string; steps: string[]; expected: string };
function parseTestCases(raw: string): TestCase[] {
const data = JSON.parse(raw); // кине помилку на битому JSON — і добре
if (!Array.isArray(data)) throw new Error('Очікувався масив кейсів');
for (const tc of data) {
if (!tc.title || !Array.isArray(tc.steps) || tc.steps.length === 0 || !tc.expected) {
throw new Error(`Неповний кейс: ${JSON.stringify(tc)}`);
}
}
return data;
}
test('вивід моделі має бути валідним масивом кейсів', () => {
const rawFromModel = `[
{ "title": "Форма приймає пароль рівно 8 символів",
"steps": ["ввести 'abcdef12'", "надіслати"],
"expected": "пароль прийнято" },
{ "title": "Форма відхиляє пароль у 7 символів",
"steps": ["ввести 'abcde12'", "надіслати"],
"expected": "помилка валідації, форма не відправлена" }
]`;
const cases = parseTestCases(rawFromModel);
expect(cases.length).toBeGreaterThan(0);
expect(cases.every((c) => c.steps.length > 0)).toBe(true);
});
Що дивитися і чому:
JSON.parseкидає на битому виводі — і це бажана поведінка. Хай зламаний JSON упаде голосно тут, а не тихо просочиться в TMS кривим кейсом.- Перевіряють не лише наявність поля, а й порожнечу. Кейс з
steps: []формально валідний за типом, але марний — асертsteps.length === 0ловить «структурно правильний, але порожній» вивід. - Гарантована схема надійніша за прохання. Якщо це продакшн-інтеграція, замість парсингу тексту краще змусити модель віддати результат за JSON-схемою через structured output / function calling — тоді структуру гарантує API, а ваш код перевіряє вже семантику.
- Локатори з такого виводу окремо звіряють з розміткою. Якщо модель у кроках згенерувала селектор, його не можна брати на віру — модель охоче вигадує елементи, яких на сторінці немає.
Анатомія промпта
- Можу назвати шість блоків сильного промпта: роль і контекст, задача, вхідні дані, обмеження, формат виводу, приклади — і сказати, який ризик закриває кожен.
- Розумію, що промпт — це технічне завдання виконавцю без контексту, а не «запит у чат»; якість виводу впирається в якість промпта, а не в «настрій» моделі.
- Знаю, чому вхідні дані відокремлюють від інструкцій (бектики або теги на кшталт
<requirements>) і що це заодно бар'єр проти prompt injection. - Можу пояснити, чому дві незалежні задачі в одному промпті краще розбити на два.
- Розумію, що діагностику слабкого виводу починають з питання «якого блоку бракує», а порожній результат — це майже завжди брак вхідних даних чи критеріїв якості.
Zero-shot, few-shot і chain-of-thought
- Знаю різницю zero-shot vs few-shot і правило «стартуй із zero-shot, додавай приклади, коли форма не збігається».
- Можу пояснити in-context learning (модель ловить патерн з прикладів у промпті без зміни ваг; one-shot — з одним зразком) і чому один показаний зразок house-стилю сильніший за абзац словесного опису формату.
- Можу пояснити, що таке chain-of-thought і що він піднімає якість на багатокрокових задачах.
- Знаю головне застереження про CoT: міркування — це правдоподібне пояснення, а не доказ; висновок усе одно перевіряють.
- Розрізняю «просити модель міркувати вголос» і «самому розкласти задачу на етапи» — reasoning-моделям перше потрібне рідше, друге корисне завжди.
Роль, формат і валідація
- Розумію, що роль зміщує словник і перспективу, але не додає знань і не робить вивід достовірним.
- Можу пояснити, чому «ти найкращий тестувальник» нічого не покращує, а «подивись очима зловмисника» — покращує.
- Знаю два рівні контролю формату: прохання в промпті vs гарантована схема (structured output / function calling) і коли який доречний.
- Розумію інваріант «заданий формат ≠ валідний формат»: вивід треба розпарсити й перевірити поля кодом, а не приймати на віру.
Ітерація і промпт як артефакт
- Можу пояснити, чому уточнення має бути адресним («додай верхню межу 64»), а не розмитим («зроби краще»).
- Знаю про дрейф контексту: після багатьох правок дешевше переписати промпт з нуля, ніж воювати латками.
- Розумію, чому вдалий промпт зберігають як багаторазовий артефакт (CLAUDE.md, скіли, слеш-команди), а не вигадують щоразу.
Ризики: галюцинації та ін'єкції
- Розумію, що впевнений тон не корелює з достовірністю: галюцинація звучить так само переконливо, як факт.
- Знаю, що модель охоче вигадує селектори й методи, яких у наданому коді/HTML немає, тож локатори з AI завжди звіряю з розміткою.
- Можу пояснити prompt injection: текст, який ви кладете у промпт як дані (лог, тікет, сторінка), може містити приховані інструкції для моделі.
Як найкраще думати про промпт для QA-задачі?
Питання
Промптинг (prompting) — що це і чому важить для QA?