Генерация BDD тестов с помощью ChatGPT и запуск их через Playwright

—

от автора

В текущих проектах я применяю подход Behavior Driven Development (BDD) для написания end‑to‑end тестов. Хотя раньше я скептически относился к Given‑When‑Then синтаксису, теперь часто его использую. Главная причина — я больше не пишу BDD‑сценарии вручную, а генерирую их с помощью ChatGPT.

В статье расскажу, как вы можете генерировать AI-тесты в своем проекте и запускать их в реальном браузере с помощью Playwright.

AI пишет тесты

AI пишет тесты

Для примера я буду использовать демо‑приложение TodoList, разработанное командой Playwright. Это веб‑страница со списком, в который можно добавлять записи, помечать их выполненными и фильтровать по статусу. Конечная цель — покрыть это приложение end‑to‑end тестами, при этом написать минимум кода вручную и делегировать максимум работы ChatGPT. В идеале тесты запускаются и проходят вообще без дополнительных правок. Ниже проверим, насколько это возможно.

TodoList

TodoList

План

А мой список дел для статьи следующий:

  1. Сформулировать требования (user story)

  2. Сгенерировать описания шагов

  3. Сгенерировать BDD сценарии

  4. Запустить тесты

  5. Подвести итог

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.

Отправляю запрос в чат и жду результат. Меня всегда немного гипнотизирует процесс авто-генерации кода ?

Generate

Генерация Page Object Model с помощью ChatGPT
Полный код из ответа 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, как и человек, может отвечать по-разному. Для меня наиболее эффективной стратегией стало:

  1. получить первичный ответ

  2. улучшить его дополнительными командами

  3. финально подправить вручную

Для примера с генерацией TodoPage это особенно релевантно, т.к. в любом случае требуется дописать реализацию методов.

2.1 Реализация методов

Реализацию методов можно писать вручную, изучая HTML-код страницы через инструменты разработчика. Но изначальная цель — сгенерировать максимум кода автоматически. К счастью, Playwright предоставляет инструмент codegen, который записывает все действия на странице в виде команд для браузера.

Режим codegen запускается через терминал:

npx playwright codegen https://demo.playwright.dev/todomvc

После этого на заданном URL открывается окно браузера, в котором достаточно выполнить необходимые действия. Например:

  1. добавить пару записей

  2. пометить выполненными

  3. отфильтровать

steps in browser

Заполнение списка дел под присмотром codegen

Сгенерированный код:

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 синтаксис, генерирует осмысленные сценарии и применяет только указанные шаги.

Как и в предыдущий раз, можно улучшить ответ:

  1. Использовать ключевое слово Background для повторяющихся действий — это аналог beforeEach()

  2. Удалить [x] из названий в таблицах — иначе сравнение записей будет выдавать ошибку

  3. Удалить заголовок 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 отчёт содержит детали по каждому сценарию:

HTML report

HTML отчёт

5. Подвести итог

Я доволен полученным результатом. Да, пришлось корректировать ответы ChatGPT, но на это ушло гораздо меньше времени, чем если бы я писал этот код вручную. Мне нравится такой способ написания тестов — не тот монотонный процесс, про который в некоторых командах иногда забивают забывают. Это современный вариант парного программирования, когда твой партнёр — нейросеть. Она не идеальная и может ошибаться, зато очень исполнительная, невероятно начитанная и готова с энтузиазмом браться за любые задачи!

BDD-формат отлично подходит для AI-генерации. Он понятный и легко читаемый. Нейросеть собирает шаги в логически правильные цепочки, а человек быстро валидирует результат и находит ошибки. При этом формат технический, сценарии можно сразу запускать в реальном браузере, используя Playwright и другие инструменты.

Уверен, есть еще много способов улучшения этого процесса. Поделитесь вашим опытом в комментариях.

Благодарю за внимание и зелёных вам тестов ❤️


ссылка на оригинал статьи https://habr.com/ru/articles/758980/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *