ビハイビア駆動開発(Behavior-Driven Development、BDD)は、テスト駆動開発(TDD)を拡張した開発手法で、ソフトウェアの振る舞い(ビハイビア)に焦点を当てます。BDDは、開発者、テスター、ビジネス関係者の間のコミュニケーションを改善し、すべての関係者が共通の言語でソフトウェアの要件を理解できるようにすることを目指しています。この手法は、Dan Northによって2006年頃に提唱されました。
TDDがテストの技術的な側面に焦点を当てるのに対し、BDDはビジネス価値と振る舞いに焦点を当てます。主な違いは以下の通りです:
BDDでは、振る舞いを「Given-When-Then」形式で記述します:
この形式は、「シナリオ」と呼ばれ、ビジネス関係者にも理解しやすい形で要件を表現します。
BDDは、ドメイン駆動設計(DDD)の概念である「ユビキタス言語」を採用しています。これは、開発者とビジネス関係者が共通の言語を使用することで、コミュニケーションの齟齬を減らし、要件の理解を深めるアプローチです。
BDDを実践するためのツールとフレームワークには以下のようなものがあります:
Cucumberは、最も広く使用されているBDDフレームワークの一つです。Gherkin構文を使用して、自然言語でシナリオを記述し、それを自動化されたテストに変換します。
Feature: ユーザーログイン
ユーザーとして
システムにログインしたい
認証された機能にアクセスするため
Scenario: 有効な認証情報でのログイン
Given ログインページにアクセスしている
When ユーザー名"user@example.com"とパスワード"password"を入力する
And ログインボタンをクリックする
Then ダッシュボードページが表示される
And "ようこそ、ユーザー"というメッセージが表示される
SpecFlowは、.NET環境でのBDDを支援するフレームワークで、CucumberのGherkin構文を使用します。
JBehaveは、Java環境でのBDDを支援するフレームワークです。
BehatはPHP環境でのBDDを支援するフレームワークです。
RSpecは、Ruby環境でのBDDを支援するフレームワークで、より技術的な構文を使用します。
describe User do
describe "#authenticate" do
context "with valid credentials" do
it "returns true" do
user = User.new(email: "user@example.com", password: "password")
expect(user.authenticate("password")).to be true
end
end
end
end
JasmineとMochaは、JavaScript環境でのBDDを支援するフレームワークです。
describe('User', function() {
describe('#authenticate', function() {
context('with valid credentials', function() {
it('returns true', function() {
const user = new User('user@example.com', 'password');
expect(user.authenticate('password')).to.be.true;
});
});
});
});
オンラインショッピングカートの機能をBDDで実装する例を見てみましょう。
Feature: ショッピングカート
顧客として
商品をカートに追加したい
購入するため
Scenario: 商品をカートに追加する
Given カタログページを表示している
When 商品"ノートパソコン"の"カートに追加"ボタンをクリックする
Then カートに商品"ノートパソコン"が追加される
And カートの合計金額が"100,000円"と表示される
Scenario: カートから商品を削除する
Given カートに商品"ノートパソコン"が入っている
When 商品"ノートパソコン"の"削除"ボタンをクリックする
Then カートから商品"ノートパソコン"が削除される
And カートの合計金額が"0円"と表示される
これらのシナリオは、Cucumberなどのツールを使用して自動化されたテストに変換できます。例えば、JavaScriptとCucumberを使用した実装は以下のようになります:
// step_definitions.js
const { Given, When, Then } = require('cucumber');
const assert = require('assert');
const ShoppingCart = require('../src/shopping_cart');
let context = {};
Given('カタログページを表示している', function() {
context.catalog = new Catalog();
});
When('商品{string}の"カートに追加"ボタンをクリックする', function(productName) {
context.cart = new ShoppingCart();
const product = context.catalog.findProduct(productName);
context.cart.addProduct(product);
});
Then('カートに商品{string}が追加される', function(productName) {
const product = context.cart.findProduct(productName);
assert.notEqual(product, null);
});
Then('カートの合計金額が{string}と表示される', function(totalPrice) {
assert.equal(context.cart.getTotalPrice(), totalPrice);
});
ユーザー認証機能をBDDで実装する例を見てみましょう。
Feature: ユーザー認証
ユーザーとして
システムに認証したい
保護されたリソースにアクセスするため
Scenario: 有効な認証情報でのログイン
Given ログインページにアクセスしている
When ユーザー名"user@example.com"とパスワード"password"を入力する
And ログインボタンをクリックする
Then ダッシュボードページにリダイレクトされる
And "ようこそ、ユーザー"というメッセージが表示される
Scenario: 無効な認証情報でのログイン
Given ログインページにアクセスしている
When ユーザー名"user@example.com"とパスワード"wrong_password"を入力する
And ログインボタンをクリックする
Then ログインページに留まる
And "無効なユーザー名またはパスワード"というエラーメッセージが表示される
BDDはTDDの拡張であり、TDDの技術的なアプローチにビジネス視点を加えたものです。TDDとBDDは相互に補完し合い、一緒に使用することができます。
ATDDは、受け入れテストを先に書いてから開発を進める手法です。BDDはATDDと多くの共通点を持ちますが、BDDはより自然言語に近い形式を使用し、ビジネス関係者の関与をより重視します。
DDDは、ビジネスドメインに焦点を当てた設計手法です。BDDはDDDの「ユビキタス言語」の概念を採用しており、両者は相補的な関係にあります。
ビハイビア駆動開発(BDD)は、テスト駆動開発(TDD)を拡張した開発手法で、ソフトウェアの振る舞いに焦点を当て、ビジネス関係者と開発者の間のコミュニケーションを改善します。BDDでは、振る舞いを「Given-When-Then」形式で記述し、それを自動化されたテストに変換します。
BDDの主な利点は、コミュニケーションの改善、共通の理解の構築、生きたドキュメントの作成、テストの自動化などです。一方で、学習曲線、ビジネス関係者の関与、シナリオの保守などの課題もあります。
BDDは、すべてのプロジェクトや状況に適しているわけではありませんが、適切に適用することで、より良いコミュニケーション、より高品質なソフトウェア、より満足度の高いユーザー体験を実現することができます。特に、ビジネス要件が複雑で変化しやすいプロジェクトや、ビジネス関係者と開発者の間のコミュニケーションが重要なプロジェクトでは、BDDの導入を検討する価値があります。