AI-автогенерація E2E-тестів
E2E-тести — найдорожчі в підтримці: ломаються при будь-якій змові UI, повільно виконуються, нестійкі (flaky). Головна причина нестійкості — жорсткі локатори типу div.container > ul > li:nth-child(3) > a. AI-генератор створює Playwright-тести з семантичними локаторами (aria-label, data-testid, role), які стійкі до косметичних змін верстки.
Генерація Playwright тестів з опису сценарію
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}
Виправ:
- Замініть CSS-селектори на semantic locators
- Видаліть непотрібні клацання
- Додайте явні очікування
- Додайте assertion для перевірки даних
Повернення покращеного TypeScript коду.""" return self.llm.invoke(prompt).content
### Оптимізація стійкості та self-healing
```python
class TestStabilityOptimizer:
async def analyze_flakiness(self, test_result: dict) -> dict:
"""Аналізує, чому тест впав та пропонує виправлення"""
prompt = f"""Проаналізуй нестійкість тесту.
Тест: {test_result['test_name']}
Помилка: {test_result['error']}
Знімок екрана: {test_result['screenshot_path']}
Ймовірні причини:
- Race condition: елемент ще не видимий
- Затримка мережі: очікуй на мережевий відповідь
- Асинхронне оновлення: вміст елемента змінив
- Динамічний ID/class: селектор потребує оновлення
Запропонуй виправлення (семантичний локатор підхід)."""
return await self.llm.ainvoke(prompt)
Кейс: React SPA, 80 критичних user journeys для E2E. Оригінальна проблема: 35% тестів нестійкі, ломаються 2–3 рази на тиждень на змінах стилю. Генеровані semantic-locator тести: нульова нестійкість після стабілізації. Час підтримки на змені верстки: 3 години (ручне виправлення на тест) → 0 (тести адаптуються).
Строки: генерація E2E тестів + покращення стійкості: 4–6 тижнів; повний фреймворк з кросс-браузерним тестуванням: 8–10 тижнів.







