AI-система автоматической генерации end-to-end тестов

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
AI-система автоматической генерации end-to-end тестов
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

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}

Проблемы Codegen-тестов которые нужно исправить:

  1. Замени хрупкие CSS-селекторы на semantic locators
  2. Добавь явные ожидания вместо неявных
  3. Вынеси тестовые данные в переменные
  4. Добавь проверки состояния (expect) после ключевых действий
  5. Разбей на логические шаги с комментариями

Верни улучшенный тест.""" return self.llm.invoke(prompt).content


### Автоматический Screenshot-to-Test

Если есть UI но нет тестов — можно генерировать тесты из скриншотов с описанием:

```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 генерация

    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 тестов

```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

Кейс: SaaS-продукт, 120 E2E-тестов в Playwright, 35% из них flaky (падали в 15–40% запусков из-за race conditions и хрупких локаторов). AI-генератор переписал 120 тестов: заменил CSS-селекторы на semantic locators, добавил правильные ожидания. Flaky rate: 35% → 4%. Время прогона упало на 22% за счёт удаления лишних waitForTimeout.

Сроки: генератор Playwright тестов + POM: 2–4 недели; с Screenshot-to-Test и flaky фиксером: 5–7 недель.