В прошлой статье "Ваш отчет никто не читает: Как мы научили разработчиков понимать падения тестов за 30 секунд?" мы разбирали, как слой Flows и декораторы позволяют разрабам не тратить время на дебаг отчетов. Сегодня хочу раскрыть "фундамент", на котором строится этот подход.

Многие годы нам продают BDD (Behavior-Driven Development) как "серебряную пулю" для коммуникации...

Давайте честно, это чушь. Никогда не понимал, зачем мы кормим этого монстра по имени Cucumber. Тратим до 50% времени на поддержку регулярок ("клея"), возимся с хрупкими .feature файлами и боимся переименовать шаг, потому что все развалится. При этом ни один менеджер в здравом уме не заходит в ваш репозиторий читать эти файлы. Они все смотрят только отчеты.

Так зачем нам Gherkin на этапе написания кода? Представляю вам новую методологию BDR (Business-Driven Living Requirements).

Почему классический BDD (Gherkin) - это ошибка?

Gherkin заставляет инженера работать внутри IDE, как в текстовом блокноте. Это абсурд.

  1. Двойная работа: Вы описываете логику в тексте, а потом "приклеиваете" её к коду. Любая опечатка и тест упал до начала работы. Вы занимаетесь корректурой, а не инженерией.

  2. Смерть типизации: Попробуйте прокинуть через Cucumber сложные объекты или использовать Rename Symbol. IDE бессильна. Вы добровольно отказываетесь от преимуществ TypeScript и других языков.

  3. Ад поддержки: Проект на 1000+ тестов с Cucumber превращается в болото из регулярок, в котором страшно что-то трогать.

Технический отчет без бизнес-контекста: просто список локаторов и селекторов
Технический отчет без бизнес-контекста: просто список локаторов и селекторов

BDR: Пишем код и получаем отчет

Моя идея проста: Нам не нужен Gherkin для написания тестов. Нам нужен Gherkin для представления результатов.

BDR (Business-Driven Living Requirements) - это Code-First подход. Например, пишем тесты на чистом TypeScript (Playwright). Используем циклы, условия, типизацию и автодополнение. Но в отчёте Allure на выходе получается идеальная бизнес-до��ументация.

Как это выглядит в тестах?

Вместо регулярок, нормальные строки с параметрами.

await BDR.When('Пользователь входит как {} с паролем {}', username, password, async (u, p) => {
    await page.fill('#user', u);
    await page.fill('#pass', p);
    await page.click('#login');
});

В чём фишка? {} - это маркер параметра. В отчёте Allure вы увидите: "WHEN: Пользователь входит как standard_user с паролем secret".

BDR в действии: Given/When/Then шаги выглядят как чистый текст
BDR в действии: Given/When/Then шаги выглядят как чистый текст

Заглянем под капот

Вы спросите: "А как это работает без магии?". На самом деле, это просто тонкая обертка над test.step. Вот как выглядит ядро движка:

const createStep = (prefix: string) => {
  return async (title: string, ...args: any[]) => {
    const body = args.pop(); // Последний аргумент - это всегда функция шага
    const stepName = `${prefix.toUpperCase()}: ${formatTitle(title, args)}`;
    return test.step(stepName, async () => {
      // Поддерживаем как обычные функции, так и функции с аргументами
      return body.length > 0 ? await body(...args) : await body();
    });
  };
};

export const BDR = {
  Given: createStep('Given'),
  When: createStep('When'),
  Then: createStep('Then'),
};

Функция formatTitle просто итерируется по аргументам и заменяет {} на значения. Никаких регулярных выражений, никакой сложной логики парсинга. IDE понимает всё: куда мы передаем функцию, какие аргументы у нас есть.

Кстати, этот же механизм лежит в основе декоратора @Step, о котором я писал в прошлой статье. Это позволяет использовать один и тот же движок форматирования и в инлайновых шагах, и в методах классов-Flows.

HTML-таблицы: То, чего всегда не хватало

Cucumber любили за таблицы. В Playwright по умолчанию таблицы превращаются в текстовое месиво в логах.

В BDR я реализовал attachTable. Это утилита, которая генерирует стилизованный HTML из обычного массива объектов и вешает его как аттачмент к Allure-шагу.

const items = [
    { name: 'Backpack', price: '$29.99' },
    { name: 'Bike Light', price: '$9.99' }
];

await attachTable('Список товаров', items);
HTML-таблица в Allure: бизнес-контекст виден сразу
HTML-таблица в Allure: бизнес-контекст виден сразу

Почему BDR победит?

Мы (инженеры) часто страдаем от того, что пытаемся быть "удобными" для бизнеса, внедряя инструменты, которые нам мешают.

BDR убирает этот конфликт:

  • Автоматизатор пишет код так, как удобно ему (Type Safety, IDE, отсутствие копипасты)

  • Бизнес видит документацию в отчётах, как и раньше

Это только для UI?

А вот и нет. BDR - это архитектурный подход, который плевать хотел на то, что вы тестируете: кнопку в браузере или API эндпоинт.

В API-тестах BDR даже нужнее. Обычно отчеты по API - это кладбище JSON-логов. С BDR вы просто оборачиваете вызовы в бизнес-Flow. В отчете это выглядит одинаково: и UI, и API шаги выстраиваются в единую логическую цепочку. Вы можете сделать честный E2E: "Создали юзера и наполнили корзину через API -> Оформили заказ в UI -> Проверили статус заказа через API". И в отчете это будет выглядеть как связная история, а не как лог сетевой активности.

Что дальше?

Верю, что будущее не за Gherkin-файлами, а за Low-Code визуальными редакторами. Работаю над концептом редактора, где мануальщик собирает тест в интерфейсе, а в итоге генерируется чистый TypeScript код.

Никакой магии, никакой хрупкости. Только чистая инженерия под капотом.

Пишите в комментариях, какие ещё "боли" Allure или сложности в Gherkin мешают вам спать спокойно?


Весь код проекта, включая движок BDR и примеры тестов, доступен здесь.


Автор: Дмитрий Сорвачев, разработчик методологии BDR.