Playwright-BDDというPlaywrightだけでBDDができるライブラリがあったので,CucumberとPlaywright使ったBDDとの比較をやってみました.
1.BDDとは
BDD(Behavior-Driven Development:振る舞い駆動開発)とは,システムがどう振る舞うべきかに焦点を当てた開発手法です.
もともとTDD(Test-Driven Development:テスト駆動開発)から派生した開発手法で,TDDはプログラムが正しく動作するかに重点を置いていました.
TDDは開発者視点で開発を進めるのに対し,BDDはシステムを使用するユーザー視点で開発を進めます.
BDDの最大の特徴はGherkin(ガーキン)記法を使用してテストケースを自然言語で作成できることです。
これにより、開発者のみでなく,POやその他関係者すべての人がテスト内容を理解できるものとなっています。
TODOリストを例にすると以下のようになります.
Scenario: 新しいTODOを追加する
Given ユーザーがTODOリストを開いている
When "本を読む" というタスクを入力し、追加ボタンを押す
Then リストに "本を読む" というタスクが表示される
2.Cucumber+Playwright
例でも使用した以下のテストケースをCucumberとPlaywrightで実装します。
CucumberはBDDでよく使用されるフレームワークです。
javascriptだけでなくJavaやPHPでも使用することができます。
Scenario: 新しいTODOを追加する
Given ユーザーがTODOリストを開いている
When "本を読む" というタスクを入力し、追加ボタンを押す
Then リストに "本を読む" というタスクが表示される
CucumberとPlaywrightをインストールします。
yarn add -D @cucumber/cucumber @playwright/test
yarn init playwright@latest
TypeScriptを使用するとデフォルトの状態で動きませんでした。
以下の記事を参考にすると動作しました。
Cucumberの設定ファイルを追加します。
module.exports = {
default: {
requireModule: ['ts-node/register'],
require: ['step_definitions/**/*.ts'],
paths: ['features/**/*.feature'],
format: ['progress-bar', 'html:cucumber-report.html'],
parallel: 2
}
}
featureファイルをfeaturesフォルダ配下に作成します。
(例 /features/todo.feature)
Feature: TODOリスト
Scenario: 新しいTODOを追加する
Given ユーザーがTODOリストを開いている
When "本を読む" というタスクを入力し、追加ボタンを押す
Then リストに "本を読む" というタスクが表示される**
step_definitionsフォルダ配下にテストファイルを作成します。
(例 /step_definitions/addTodo.steps.ts)
import { Given, When, Then, Before, After } from '@cucumber/cucumber';
import { chromium, Browser, Page, expect } from '@playwright/test';
let browser: Browser;
let page: Page;
// フック:ブラウザの起動
Before(async () => {
browser = await chromium.launch({ headless: true });
page = await browser.newPage();
});
Given('ユーザーがTODOリストを開いている', async () => {
await page.goto('http://localhost:5174');
});
When('{string} というタスクを入力し、追加ボタンを押す', async (task: string) => {
await page.fill('input.new-todo', task);
await page.click('button.add-btn');
});
Then('リストに {string} というタスクが表示される', async (task: string) => {
await expect(page.locator('.todo-list')).toContainText(task);
});
// フック:ブラウザの終了
After(async () => {
await browser.close();
});
テストを実行するには以下のコマンドを入力します。
yarn cucumber-js
3.Playwright-BDD
同様に、以下のテストケースをPlaywright-BDDで実装します。
Scenario: 新しいTODOを追加する
Given ユーザーがTODOリストを開いている
When "本を読む" というタスクを入力し、追加ボタンを押す
Then リストに "本を読む" というタスクが表示される
Playwright-BDDをインストールします。
yarn add -D @playwright/test playwright-bdd
yarn init playwright@latest
playwright.config.jsを以下のように変更します。
import { defineConfig } from '@playwright/test';
import { defineBddConfig } from 'playwright-bdd';
const testDir = defineBddConfig({
features: 'features/*.feature',
steps: 'step_definitions/*.ts',
});
export default defineConfig({
testDir,
reporter: 'html',
});
featureファイルをfeaturesフォルダ配下に作成します。
(例 /features/todo.feature)
Feature: TODOリスト
Scenario: 新しいTODOを追加する
Given ユーザーがTODOリストを開いている
When "本を読む" というタスクを入力し、追加ボタンを押す
Then リストに "本を読む" というタスクが表示される**
step_definitionsフォルダ配下にテストファイルを作成します。
(例 /step_definitions/addTodo.steps.ts)
import { createBdd } from 'playwright-bdd';
import { expect } from '@playwright/test';
const { Given, When, Then } = createBdd();
// { page } フィクスチャが自動で注入されるため、Before/Afterの記述が不要!
Given('ユーザーがTODOリストを開いている', async ({ page }) => {
await page.goto('http://localhost:5174');
});
When('{string} というタスクを入力し、追加ボタンを押す', async ({ page }, task: string) => {
await page.fill('input.new-todo', task);
await page.click('button.add-btn');
});
Then('リストに {string} というタスクが表示される', async ({ page }, task: string) => {
await expect(page.locator('.todo-list')).toContainText(task);
});
テストを実行するには以下のコマンドを入力します。
yarn bddgen && yarn playwright test
npx bddgen を実行すると、ライブラリがfeatureとstepを合体させて、.features-gen/addTodo.spec.ts というファイルを自動生成します。
4.実装
todoリストに追加するテストを作成したので実装に入ります。
作成したシナリオ通りの画面を作りました。

テストを実行します。
テストが成功すると以下のように表示されます。
まとめ
Cucumber+PlaywrightとPlaywright-BDDを比較してみました。
CucumberとTypeScriptの相性が悪くインストールの時点で時間がかかってしまいました。
Playwright-BDDは、GherkinをPlaywrightのテストコードに変換するためPlaywrightの機能を活用することができます。デバックの際にPlaywrightのUIモードなども使用できるのが大きな強みです。
これからPlaywrightでBDDを導入する際はPlaywright-BDDを使用してみてください。
参考

