В текущих проектах я применяю подход Behavior Driven Development (BDD) для написания end‑to‑end тестов. Хотя раньше я скептически относился к Given‑When‑Then синтаксису, теперь часто его использую. Главная причина — я больше не пишу BDD‑сценарии вручную, а генерирую их с помощью ChatGPT.
В статье расскажу, как вы можете генерировать AI-тесты в своем проекте и запускать их в реальном браузере с помощью Playwright.
Для примера я буду использовать демо‑приложение TodoList, разработанное командой Playwright. Это веб‑страница со списком, в который можно добавлять записи, помечать их выполненными и фильтровать по статусу. Конечная цель — покрыть это приложение end‑to‑end тестами, при этом написать минимум кода вручную и делегировать максимум работы ChatGPT. В идеале тесты запускаются и проходят вообще без дополнительных правок. Ниже проверим, насколько это возможно.
План
А мой список дел для статьи следующий:
-
Сформулировать требования (user story)
-
Сгенерировать описания шагов
-
Сгенерировать BDD сценарии
-
Запустить тесты
-
Подвести итог
1. Сформулировать требования (user story)
Пользовательская история (user story) — важнейший элемент BDD. Это описание действий пользователя для достижения конкретной цели в приложении. Для тестирования TodoList возьмём следующие требования:
As a user I want to manage items in todo list: create items, complete items and filter to see only completed items.
Все тексты, относящиеся к запросам в ChatGPT, будут на английском — прим. переводчика.
Дальше я буду использовать этот текст в запросах к ChatGPT.
2. Сгенерировать описания шагов
Описание шага (step definition) — это конкретная реализация действия пользователя. Например:
Given I open TodoApp page
превращается в команду для браузера:
await page.goto('https://demo.playwright.dev/todomvc/');
Или
When I click the button
становится:
await page.getByTestId('button').click();
Набор описаний шагов можно объединить в Page Object Model — класс, соответствующий определенной странице приложения в тестовых сценариях.
Для списка дел потребуется один класс TodoPage с методами для создания, маркировки и фильтрации записей. Сложность в том, что реализация шагов сильно зависит от структуры HTML, поэтому я не буду делегировать это искусственному интеллекту. Но… ChatGPT отлично справится с генерацией шаблона для такого класса.
На выходе я хочу получить код на TypeScript с использованием пакетов @playwright/test и playwright-bdd — чтобы потом запустить эти тесты на Playwright.
Запрос к ChatGPT для генерации шаблона TodoPage :
Create Page Object Model 'TodoPage' in Typescript for the following feature: As a user I want to manage items in todo list: create items, complete items and filter to see only completed items. * Use page from '@playwright/test' as constructor parameter. * Use Given, When, Then from 'playwright-bdd/decorators' as BDD decorators, for example: @Given('pattern {string}'). * Don't fill methods body.
Отправляю запрос в чат и жду результат. Меня всегда немного гипнотизирует процесс авто-генерации кода ?
Полный код из ответа ChatGPT
import { Page } from '@playwright/test'; import { Given, When, Then } from 'playwright-bdd/decorators'; export class TodoPage { private page: Page; constructor(page: Page) { this.page = page; } @Given('I am on the Todo page') async navigateToTodoPage() { // Implement navigation to the Todo page here } @When('I create a new todo item with text {string}') async createTodoItem(text: string) { // Implement creating a new todo item here } @When('I complete the todo item with text {string}') async completeTodoItem(text: string) { // Implement completing a todo item here } @When('I filter to see only completed items') async filterCompletedItems() { // Implement filtering completed items here } @Then('I should see the todo item with text {string}') async verifyTodoItemVisible(text: string) { // Implement verification logic here } @Then('I should not see the todo item with text {string}') async verifyTodoItemNotVisible(text: string) { // Implement verification logic here } @Then('I should see only completed todo items') async verifyOnlyCompletedItemsVisible() { // Implement verification logic here } @Then('I should see all todo items') async verifyAllItemsVisible() { // Implement verification logic here } }
Получилось неплохо: ChatGPT сгенерировал необходимые методы, пометил их правильными декораторами и прокинул параметры там, где это нужно.
Теперь я хочу улучшить результат. Вместо 4-х методов верификации оставить один, который сверяет список целиком. Это удобнее, чем проверять записи по одной. Отправляю запрос в чат обычным текстом и получаю исправленный ответ.
Уточняющий запрос:
Replace all verify methods with single method that verifies list of visible items
Ответ ChatGPT (обратите внимание на последний метод)
import { Page } from '@playwright/test'; import { Given, When, Then } from 'playwright-bdd/decorators'; export class TodoPage { private page: Page; constructor(page: Page) { this.page = page; } @Given('I am on the Todo page') async navigateToTodoPage() { // Implement navigation to the Todo page here } @When('I create a new todo item with text {string}') async createTodoItem(text: string) { // Implement creating a new todo item here } @When('I complete the todo item with text {string}') async completeTodoItem(text: string) { // Implement completing a todo item here } @When('I filter to see only completed items') async filterCompletedItems() { // Implement filtering completed items here } @Then('I should see the following todo items:') async verifyTodoItemsVisible(itemList: string[]) { for (const itemText of itemList) { // Implement verification logic for each itemText here } } }
Все исправлено. ChatGPT заменил часть методов, а остальные оставил нетронутыми.
Важно заметить, если вы отправите такие же запросы в ChatGPT, вы получите другие результаты, лучше ли хуже. Я специально провёл несколько экспериментов на чистых сессиях. Вот примеры команд, которые помогут улучшить ответ:
-
make all methods async— иногда ChatGPT генерирует синхронные методы -
use {string} for string pattern parameters— использовать корректный синтакс Cucumber Expression для параметров -
create todo items inside scenario "xxx"— исправить сценарии, которые используют данные других сценариев, тесты должны быть изолированы -
don't start method names with given/when/then— для более лаконичных имён методов
Важно не пытаться получить идеальный результат. ChatGPT, как и человек, может отвечать по-разному. Для меня наиболее эффективной стратегией стало:
-
получить первичный ответ
-
улучшить его дополнительными командами
-
финально подправить вручную
Для примера с генерацией TodoPage это особенно релевантно, т.к. в любом случае требуется дописать реализацию методов.
2.1 Реализация методов
Реализацию методов можно писать вручную, изучая HTML-код страницы через инструменты разработчика. Но изначальная цель — сгенерировать максимум кода автоматически. К счастью, Playwright предоставляет инструмент codegen, который записывает все действия на странице в виде команд для браузера.
Режим codegen запускается через терминал:
npx playwright codegen https://demo.playwright.dev/todomvc
После этого на заданном URL открывается окно браузера, в котором достаточно выполнить необходимые действия. Например:
-
добавить пару записей
-
пометить выполненными
-
отфильтровать
Сгенерированный код:
test('test', async ({ page }) => { await page.goto('https://demo.playwright.dev/todomvc/#/'); await page.getByPlaceholder('What needs to be done?').fill('feed the dog'); await page.getByPlaceholder('What needs to be done?').press('Enter'); await page.getByPlaceholder('What needs to be done?').fill('feed the cat'); await page.getByPlaceholder('What needs to be done?').press('Enter'); await page.locator('li').filter({ hasText: 'feed the cat' }).getByLabel('Toggle Todo').check(); await page.getByRole('link', { name: 'Completed' }).click(); });
Из этого кода я выбираю нужные фрагменты и вставляю их в шаблон от ChatGPT.
В некоторых местах ручных правок не избежать. Например, получение DOM элементов через селектор page.locator('li') я заменю на более надежный page.getByTestId('todo-title').
Финальный класс TodoPage со всеми доработками:
TodoPage.ts
import { Page, expect } from '@playwright/test'; import { Given, When, Then, Fixture } from 'playwright-bdd/decorators'; import { DataTable } from '@cucumber/cucumber'; export @Fixture('todoPage') class TodoPage { private page: Page; constructor(page: Page) { this.page = page; } @Given('I am on the Todo page') async navigateToTodoPage() { await this.page.goto('https://demo.playwright.dev/todomvc/#/'); } @When('I create a new todo item with text {string}') async createTodoItem(text: string) { await this.page.getByPlaceholder('What needs to be done?').fill(text); await this.page.getByPlaceholder('What needs to be done?').press('Enter'); } @When('I complete the todo item with text {string}') async completeTodoItem(text: string) { await this.page.getByTestId('todo-item').filter({ hasText: text }).getByLabel('Toggle Todo').check(); } @When('I filter to see only completed items') async filterCompletedItems() { await this.page.getByRole('link', { name: 'Completed' }).click(); } @Then('I should see the following todo items:') async verifyTodoItemsVisible(itemList: DataTable) { await expect(this.page.getByTestId('todo-title')).toHaveText(itemList.raw().flat()); } }
3. Сгенерировать BDD сценарии
Теперь всё готово для генерации BDD сценариев из созданных шагов. Важно указать ChatGPT использовать только конкретные шаги, чтобы в последующем запускать полученные сценарии без дополнительных правок.
Можно зайти и с другой стороны: сначала генерировать сценарии, а потом реализовывать шаги. Но в этом случае, если вы решите пересоздать сценарии, то придётся обновлять описания шагов в коде
Для получения списка доступных шагов в playwright-bdd есть специальная команда bddgen export. Она собирает описания шагов из всех файлов и выводит их в текстовом виде.
Запуск команды и вывод списка шагов из TodoPage:
> npx bddgen export List of all steps found by config: playwright.config.ts * Given I am on the Todo page * When I create a new todo item with text {string} * When I complete the todo item with text {string} * When I filter to see only completed items * Then I should see the following todo items:
Полученный список шагов я вставляю в запрос к ChatGPT.
Запрос для генерации BDD сценариев:
Generate BDD scenarios as a single Gherkin file strictly using only the following steps: * Given I am on the Todo page * When I create a new todo item with text {string} * When I complete the todo item with text {string} * When I filter to see only completed items * Then I should see the following todo items:
Ответ ChatGPT
Feature: Todo List Management Scenario: Create a new todo item Given I am on the Todo page When I create a new todo item with text "Buy groceries" Then I should see the following todo items: | Todo Text | | Buy groceries | Scenario: Complete a todo item Given I am on the Todo page When I create a new todo item with text "Read a book" And I complete the todo item with text "Read a book" Then I should see the following todo items: | Todo Text | | [x] Read a book | Scenario: Filter completed items Given I am on the Todo page When I create a new todo item with text "Walk the dog" And I create a new todo item with text "Water the plants" And I complete the todo item with text "Walk the dog" And I filter to see only completed items Then I should see the following todo items: | Todo Text | | [x] Walk the dog | Scenario: Filter completed items with multiple completed items Given I am on the Todo page When I create a new todo item with text "Go for a run" And I create a new todo item with text "Write code" And I complete the todo item with text "Go for a run" And I complete the todo item with text "Write code" And I filter to see only completed items Then I should see the following todo items: | Todo Text | | [x] Go for a run | | [x] Write code |
Результат снова неплох. ChatGPT корректно использует Given-When-Then синтаксис, генерирует осмысленные сценарии и применяет только указанные шаги.
Как и в предыдущий раз, можно улучшить ответ:
-
Использовать ключевое слово
Backgroundдля повторяющихся действий — это аналогbeforeEach() -
Удалить
[x]из названий в таблицах — иначе сравнение записей будет выдавать ошибку -
Удалить заголовок
Todo Textв таблицах — он тут лишний, т. к. всего одна колонка
Уточняющий запрос:
* Use "Background" for common steps. * Don't use "[x]" * Don't use "Todo Text" header
Обновленный ответ ChatGPT
Feature: Todo List Management Background: Given I am on the Todo page Scenario: Create a new todo item When I create a new todo item with text "Buy groceries" Then I should see the following todo items: | Buy groceries | Scenario: Complete a todo item When I create a new todo item with text "Read a book" And I complete the todo item with text "Read a book" Then I should see the following todo items: | Read a book | Scenario: Filter completed items When I create a new todo item with text "Walk the dog" And I create a new todo item with text "Water the plants" And I complete the todo item with text "Walk the dog" And I filter to see only completed items Then I should see the following todo items: | Walk the dog | Scenario: Filter completed items with multiple completed items When I create a new todo item with text "Go for a run" And I create a new todo item with text "Write code" And I complete the todo item with text "Go for a run" And I complete the todo item with text "Write code" And I filter to see only completed items Then I should see the following todo items: | Go for a run | | Write code |
Необходимые правки внесены. Настал момент запустить это в браузере!
4. Запустить тесты
Запуск BDD тестов не поддерживается в Playwright из коробки, хотя это один из самых популярных запросов. Для данной задачи я использую интеграцию playwright-bdd. Все шаги и сценарии уже написаны, поэтому осталось добавить конфигурацию.
Для краткости я опущу установку зависимостей. Вы можете посмотреть готовый репозиторий на GitHub со всеми файлами из статьи. Попробуйте сгенерировать свои BDD сценарии для TodoList и запустить их на шагах из примера.
Конфигурация для Playwright следующая:
playwright.config.ts
import { defineConfig } from '@playwright/test'; import { defineBddConfig } from 'playwright-bdd'; const testDir = defineBddConfig({ paths: ['./features/todopage.feature'], // <- BDD сценарии importTestFrom: 'steps/fixtures.ts', // <- описания шагов }); export default defineConfig({ testDir, reporter: 'html', });
Файл fixtures.ts подключает созданный ранее TodoPage в виде фикстуры:
steps/fixtures.ts
import { test as base } from 'playwright-bdd'; import { TodoPage } from './TodoPage'; export const test = base.extend<{ todoPage: TodoPage }>({ todoPage: async ({ page }, use) => use(new TodoPage(page)), });
Запускаем тесты:
npx bddgen && npx playwright test
Результат:
Running 4 tests using 1 worker 4 passed (2.7s) To open last HTML report run: npx playwright show-report
Все тесты прошли! Ура ?
HTML отчёт содержит детали по каждому сценарию:
5. Подвести итог
Я доволен полученным результатом. Да, пришлось корректировать ответы ChatGPT, но на это ушло гораздо меньше времени, чем если бы я писал этот код вручную. Мне нравится такой способ написания тестов — не тот монотонный процесс, про который в некоторых командах иногда забивают забывают. Это современный вариант парного программирования, когда твой партнёр — нейросеть. Она не идеальная и может ошибаться, зато очень исполнительная, невероятно начитанная и готова с энтузиазмом браться за любые задачи!
BDD-формат отлично подходит для AI-генерации. Он понятный и легко читаемый. Нейросеть собирает шаги в логически правильные цепочки, а человек быстро валидирует результат и находит ошибки. При этом формат технический, сценарии можно сразу запускать в реальном браузере, используя Playwright и другие инструменты.
Уверен, есть еще много способов улучшения этого процесса. Поделитесь вашим опытом в комментариях.
Благодарю за внимание и зелёных вам тестов ❤️
ссылка на оригинал статьи https://habr.com/ru/articles/758980/
Добавить комментарий