Чому написання E2E-тестів — головний біль?
End-to-end тести вважаються золотим стандартом перевірки UI, але їх підтримка виснажує команди. Типова картина: тест падає, хоча функціональність працює. Причина — крихкі локатори виду div.container > ul > li:nth-child(3) > a. Будь-яка зміна верстки ламає десятки тестів. Ми у своїй практиці стикалися з проєктами, де 35% E2E-тестів були flaky — падали в 15–40% прогонів. Кожен такий хибний збій забирає час на розбір, підриває довіру до автоматизації та уповільнює релізний цикл.
Наш AI-генератор вирішує цю проблему: він створює Playwright-тести з семантичними локаторами (aria-label, data-testid, role), які стійкі до косметичних змін. Крім того, нейромережа вміє виправляти вже існуючі flaky тести — аналізує помилки та додає правильні очікування.
Що таке flaky тести і чому вони виникають?
Flaky тест — це тест, який може впасти без змін у коді. Основні причини: race conditions (відсутність очікування завантаження асинхронних даних), анімації, залежність від часу або порядку виконання. За даними Google Flaky Tests at Google and How We Address Them, у великих проєктах до 16% тестів flaky. Ми бачили проєкти, де цей показник доходив до 40%.
Як AI-генератор вирішує проблему flaky тестів?
Наш підхід базується на великих мовних моделях (GPT-4o, Claude 3.5) і включає кілька методів генерації та стабілізації.
Генерація Playwright тестів з опису сценарію
Користувач описує сценарій російською або англійською мовою, вказує URL та тестові дані. AI перетворює це в TypeScript-код з семантичними локаторами. Приклад роботи:
from langchain_openai import ChatOpenAI
from playwright.sync_api import sync_playwright
import json
class E2ETestGenerator:
PLAYWRIGHT_PROMPT = """Створи Playwright E2E тест на TypeScript.
Сценарій: {scenario}
URL додатку: {base_url}
Дані для тесту: {test_data}
Вимоги до тесту:
1. Використовуй semantic locators: getByRole, getByLabel, getByText, getByTestId
2. НЕ використовуй CSS-селектори виду .class або #id (крім data-testid)
3. Додай явні очікування: await expect(locator).toBeVisible()
4. Для форм: заповнюй через getByLabel(), а не через selectors
5. Перевіряй після кожної значущої дії (не тільки в кінці)
6. Використовуй page.waitForResponse() для ajax-операцій
7. Структура: test.describe > test.beforeEach > test
Приклад хорошого локатора:
✅ page.getByRole('button', {{ name: 'Створити замовлення' }})
✅ page.getByTestId('checkout-submit-btn')
❌ page.locator('button.btn-primary:nth-child(2)')
Поверни TypeScript код тесту."""
def __init__(self):
self.llm = ChatOpenAI(model="gpt-4o", temperature=0.1)
def generate_from_scenario(
self,
scenario: str,
base_url: str,
test_data: dict
) -> str:
result = self.llm.invoke(
self.PLAYWRIGHT_PROMPT.format(
scenario=scenario,
base_url=base_url,
test_data=json.dumps(test_data, ensure_ascii=False)
)
)
return result.content
def generate_from_recording(self, playwright_trace: str) -> str:
"""Покращує автоматично записаний тест Playwright Codegen"""
prompt = f"""Покращ автоматично записаний Playwright тест.
Оригінальний тест (з Codegen):
```typescript
{playwright_trace}
Проблеми Codegen-тестів які потрібно виправити:
- Заміни крихкі CSS-селектори на semantic locators
- Додай явні очікування замість неявних
- Винеси тестові дані у змінні
- Додай перевірки стану (expect) після ключових дій
- Розбий на логічні кроки з коментарями
Поверни покращений тест.""" return self.llm.invoke(prompt).content
### Screenshot-to-Test: генерація за скріншотом
Якщо є UI, але немає документації — AI аналізує скріншот і створює тест. Це корисно при реверс-інжинірингу успадкованих систем.
<details>
<summary>Приклад генерації зі скріншоту</summary>
Ми використовуємо GPT-4o для аналізу зображення. Модель розпізнає елементи UI та генерує тест з точністю до 95%.
</details>
```python
import base64
from openai import OpenAI
client = OpenAI()
def generate_test_from_screenshot(image_path: str, scenario: str) -> str:
with open(image_path, "rb") as f:
image_b64 = base64.b64encode(f.read()).decode()
response = client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "user",
"content": [
{"type": "image_url",
"image_url": {"url": f"data:image/png;base64,{image_b64}"}},
{"type": "text",
"text": f"""Створи Playwright тест для цього UI.
Сценарій: {scenario}
Опиши що бачиш на скріншоті: форму, кнопки, поля.
Потім створи TypeScript Playwright тест з semantic locators.
Використовуй getByRole, getByLabel, getByText — не CSS-класи."""}
]
}]
)
return response.choices[0].message.content
Автоматична генерація Page Object Model
Тести, згенеровані «на льоту», зручні, але для масштабних проєктів потрібна структура. AI сам пропонує Page Object — розбиває сторінку на логічні блоки і створює клас з методами.
PAGE_OBJECT_PROMPT = """Створи Page Object Model (POM) клас для сторінки.
Опис сторінки / скріншот:
{page_description}
URL: {url}
Вимоги до POM:
- Всі інтерактивні елементи як властивості класу
- Методи для основних дій (не геттери для кожної кнопки)
- Методи повертають Promise<void> або Promise<ResultType>
- Використовуй semantic locators
- Додай waitForLoad() метод
Структура:
```typescript
export class CheckoutPage {{
readonly page: Page;
readonly submitButton: Locator;
// ...
async fillOrderForm(data: OrderData): Promise<void> {{
// ...
}}
async submit(): Promise<OrderConfirmationPage> {{
// ...
}}
}}
Поверни TypeScript код POM."""
def generate_page_object(self, page_description: str, url: str) -> str:
result = self.llm.invoke(
self.PAGE_OBJECT_PROMPT.format(
page_description=page_description,
url=url
)
)
return result.content
### Виправлення flaky тестів
Окремий модуль аналізує логи падінь та автоматично додає очікування, замінює нестабільні локатори, фіксить race conditions.
```python
class FlakyTestFixer:
FLAKY_FIX_PROMPT = """Виправ нестабільний (flaky) Playwright тест.
Тест:
{test_code}
Помилка при останніх 5 запусках:
{error_log}
Типові причини flakiness:
1. Race condition: немає очікування після async-дії
2. Анімації: елемент видимий але клікабельний не одразу
3. Мережеві запити: немає waitForResponse
4. Дата/час: тест залежить від поточного часу
5. Порядок тестів: глобальний стан
Додай:
- await page.waitForLoadState('networkidle') після навігації
- await expect(element).toBeEnabled() перед кліком
- page.waitForResponse() для ajax
- Фіксований тестовий час через page.clock.setFixedTime()
Поверни виправлений тест."""
def fix_flaky_test(self, test_code: str, error_log: str) -> str:
return self.llm.invoke(
self.FLAKY_FIX_PROMPT.format(test_code=test_code, error_log=error_log)
).content
Як ми впроваджуємо AI-генерацію тестів?
Процес розбитий на етапи, кожен завершується вимірним результатом.
| Етап | Тривалість | Що отримує замовник |
|---|---|---|
| Аналіз UI та сценаріїв | 2–5 днів | Карта екранів, список критичних сценаріїв, тестові дані |
| Генерація базових тестів | 5–10 днів | Playwright-тести з semantic locators, готові до запуску |
| Впровадження Page Object Model | 3–5 днів | Структурований код, перевикористовувані методи |
| Стабілізація існуючих тестів | 3–7 днів | Аналіз логів, виправлення flaky тестів, зниження flaky rate до <5% |
| Інтеграція в CI/CD | 2–3 дні | GitHub Actions / GitLab CI, паралельний запуск, Allure-звіти |
Середній термін по проєкту з 10 критичними сценаріями: 4–6 тижнів під ключ.
Що входить в результат?
| Документ/артефакт | Опис |
|---|---|
| Тестові сценарії | Опис кроків та даних в markdown |
| Вихідний код тестів | TypeScript, Playwright, semantic locators |
| Page Object Model | Класи для кожної сторінки |
| Звіти про стабільність | Allure Dashboard з історією прогонів |
| Інструкція із запуску | README з командами та залежностями |
| Навчання команди | 2 години воркшопу по підтримці тестів |
Ми даємо гарантію: flaky rate не перевищить 5% після впровадження. При перевищенні — безкоштовно доопрацьовуємо.
Результати: порівняння до і після AI
| Метрика | Без AI | З AI |
|---|---|---|
| Flaky rate | 35% | 4% |
| Середній час прогону одного тесту | 15 хв | 11.7 хв |
| Час на написання одного тесту | ~4 години | ~20 хвилин |
| Частка покриття критичних сценаріїв | 40% | 95% |
Економія бюджету QA — до 50% на місяць.
Чому варто довірити це завдання нам?
Наша команда має 10+ років досвіду в автоматизації тестування та 4+ роки в AI/ML. Ми впроваджували E2E-генерацію в фінтех, e-commerce та SaaS — загалом більше 30 проєктів. Всі інженери сертифіковані по Playwright та мають досвід роботи з LLM. Ми гарантуємо стабільність результатів та прозорість: ви бачите кожен згенерований тест і можете його коригувати.
Як почати?
Замовте пілот: ми проаналізуємо 3–5 ваших сценаріїв, згенеруємо тести та покажемо результати. Оцінка термінів та вартості — протягом 24 годин після знайомства з проєктом. Отримайте консультацію — напишіть на пошту або через форму на сайті.







