🥒

「The BDD Books」を読んで学んだことー振る舞い駆動開発に入門しました

に公開

最近、チームでの仕様の認識齟齬や手戻りに課題を感じていて、何か良いアプローチはないかと探していたところ、「BDD(振る舞い駆動開発)」に行き着きました。

BDD を学ぶにはどうすると良いか色々と調べていたところ、 The BDD Books - DiscoveryThe BDD Books - Formulation という書籍を発見したので、この記事ではこれらの本で得た気づきなどをまとめていこうと思います。

BDD の概要

BDD は開発チームとビジネスチームが協調し、これから作るソフトウェアの「振る舞い」について共通の理解を築くためのコミュニケーションアプローチに重きを置く開発プロセスです。
※振る舞い = ユーザーシナリオ、と置き換えて読んでも個人的には良いと思います

BDD の提唱者である Dan North 氏は、開発者が「テスト」という言葉に固執することで、ビジネス要件とのつながりを見失いがちであると考え、「テスト」の代わりに「振る舞い」という言葉を使うことを提唱しました。

BDD のプロセスでは、「具体例」をコミュニケーションの中心に据えます。
曖昧な仕様書とにらめっこする代わりに、「もしユーザーがこういう状況でこういう操作をしたら、どうなるべきか?」といった具体的な例をビジネスチームのメンバーと共に話し合うことで、要件の誤解や思い込みをなくしていきます。
要するに、 BDD のアプローチの働きかけによって仕様バグ・実装バグが作り込まれることを防ぐ、ということが一番の目的です。

このアプローチを取り入れることで、チームは以下のようなメリットを得ることができると言われています。

  • 手戻りの削減
    • 実装前に仕様の認識齟齬をなくすことで、開発終盤での「思っていたのと違う」を防ぎます。
  • 開発サイクルの短縮
    • チーム全体の共通理解が深まり、コミュニケーションロスが減ることで開発がスムーズに進みます。
  • 高品質なソフトウェア
    • ビジネスチームが本当に望んでいる価値を提供しやすくなり、本番環境での問題も減ります。

BDD の核心 - 3つのプラクティスと「生きているドキュメント」

BDD は以下の3つのプラクティスで構成されています。

  1. 発見 (Discovery): 具体例を使い、関係者で対話しながら仕様のあいまいさをなくす。
  2. 定式化 (Formulation): 発見した具体例を、ビジネスチームも読めるシナリオに落とし込む。
  3. 自動化 (Automation): 定式化したシナリオを自動テストに変換する。

先に振る舞いを具体例で形成してから実装に入る。この流れが作れれば、確かに手戻りは減りそうです。

そして、このサイクルから生まれるドキュメントを「The BDD Books」では生きているドキュメントと呼称していました。それは、コードとドキュメントが常に一致している状態だからです。
テストが通るということは、ドキュメントに書かれた仕様が満たされていることの証明になる。これなら出戻りを防げそうと感じます。

発見フェーズ

じゃあ、どうやって仕様の認識を合わせるのか。その具体的な手法が **「実例マッピング」**です。

これは、ユーザーストーリーを軸に、「ルール」「具体例」「疑問点」を付箋などを使って洗い出していくワークショップです。前述したように、これはビジネスチームのメンバーも一緒におこなった方が良いです。

  • ストーリー(黄色) → 議論の対象となるユーザーストーリー、デリバリーしたい価値
  • ルール(青) → ストーリーに含まれるビジネスルール。受け入れ基準と読み換えても問題ありません。
  • 具体例(緑) → ルールを説明するための振る舞い。シナリオ。
  • 疑問点(赤) → 議論中に出てきた不明点や確認事項

※上記記載の色は例です。

物理的な付箋を使うのが理想ですが、 Miro や FigJam のようなツールで実践しても良いと思います。
色分けルールを決めておけば、オンラインでもスムーズに進められそうです。

この活動を通して、あいまいだった仕様が具体的な例として可視化され、チーム内の認識齟齬を減らす効果が期待できます。

定式化フェーズ

BRIEF の原則

実例マッピングで見つけた「具体例」は、誰が読んでも分かりやすいシナリオとしてドキュメントに記述すべきです。なぜならこれはビジネスチームも閲覧することを想定しているので。
このとき、ドキュメントを書くための指針となるのが BRIEF の原則です。

  • Business language: ビジネス用語で書く
  • Real data: 具体的な実データを使う
  • Intention revealing: 「どうやるか」ではなく「何をしたいか」を書く
  • Essential: 本質的でない情報は削ぎ落とす
  • Focused: 1つのルールに焦点を当てる
  • Brief: 簡潔に書く

Gherkin 記法

定式化フェーズで記述するドキュメントは、 Gherkin 記法 を使います。これは Given-When-Then 構造で記述されるドキュメントです。
例えば以下のような形です。

Scenario: お客様が受け取り時に支払うことを選択した
  Given お客様は店頭受け取りでの注文を選択した
  When 彼らは支払い指示に進みます
  Then 彼らは受け取り時の支払いを選択できるはずです

本を読んでいて「なるほど」と思ったテクニックをいくつか紹介します。

  • Given は状態、 When はアクション
    • Given では事前の状態を説明し、 When でユーザーの操作やイベントを記述
  • When と Then は1つが基本
    • 1つのシナリオでは、1つのアクションと、それによって引き起こされる1つの結果に絞るのが理想
  • Scenario Outline でシナリオをまとめる
    • 同じ構造のシナリオが複数ある場合、 Scenario OutlineExamples テーブルを使うと DRY 書ける。
    • ただこれは乱用すると読みにくそうだなと感じました。定式化で書くドキュメントは境界値チェックのためのテスト観点を書くものではないので、そこは意識したいところです。
    Scenario Outline: ピザの残りを説明する
      Given ディナーの客はピザを<ピザ1枚あたりのスライス数>のスライスに切ります
      When 彼らは<スライスを食べた数>だけスライスを食べます
      Then <残りのスライス数>が残っているべきです
    
      Examples:
        | 説明               | ピザ1枚あたりのスライス数 | 食べたスライス数 | 残りのスライス数 |
        | まったく空腹ではない | 6                       | 0              | すべて           |
        | かなりお腹がすいた   | 6                       | 4              | 2              |
    

「The BDD Books」曰く、
複数の結果を And で繋ぐことも可能ですが、それはシナリオが複数のルールを含んでいるサインかもしれません、とのこと。
このあたりの見極めは慣れが必要そうですね。 AI の力を借りてなんとかする方法もありそうですが。

「生きているドキュメント」を育てるための feature ファイルの整理術

上記のようにシナリオを書きためていくと、今度は「どこに何が書いてあるかわからない」という問題が出てきそうです。そうならないための整理術も紹介されていました。

「The BDD Books」では、一貫性のある機能ごとに feature ファイルを作成した方が良い。ユーザーストーリーごとに作成するべきではない といった旨の記載がありました。

あくまでもユーザーストーリーは「会話のきっかけ」であり、流動的なもの。一方で feature ファイルはプロダクトの「機能」を反映した安定的なドキュメントであるべき、という考え方のようです。
例えば、 payment.featureuser_authentication.feature のように、機能単位でファイルを作成していきます。

「生きているドキュメント」に加えてドメイン用語集を作り、チーム内で共通言語を育てることも重要です。
さらにタグを使って「@manual_test_only」のようにメタ情報を付与するのもテクニックの一つであるとのことです。
※ @manual_test_only タグを付与したシナリオは、テストを自動生成しないことを示します

自動化フェーズ

発見と定式化のプラクティスを経て作成されたシナリオは、最後のプラクティスである「自動化」によって、価値を発揮します。

Gherkin 記法で定式化されたシナリオと、アプリケーションの実際のコードをグルーコードと呼ばれる接着剤の役割を持つコードで結びつけます。
これにより、シナリオは単なるドキュメントではなく、実行可能なテストへと変わります。 CI/CD パイプラインでこれらのテストを継続的に実行することで、ドキュメントと実装の間に乖離が生まれれば即座に検知できます。
テストが通っている限り、そのドキュメントは「生きている」と言えるわけです。

自動化フェーズに活躍する主要なライブラリーだと、以下のようなものでしょうか。
https://github.com/cucumber

ちなみに色々と調べたところ、私が普段使いしている PHP では特に有効なライブラリーは見つけられませんでした...
PHPer 界隈だと、 BDD のコミュニティはそこまで盛り上がってなさそう?です。

PHP と BDD におけるテスト自動化ライブラリ

先日、PHP/Laravel 環境における BDD のテストコード自動生成ライブラリについて Claude の Research 機能で調査しました。
結論から言うと、 PHP の BDD エコシステムは機能しているものの、テストコードを完全に自動生成するような決定的なライブラリは存在しないようです。

以下に主要なライブラリとその特徴をまとめます。

  • Behat
    • PHP の BDD における事実上の標準で、 Gherkin 構文をサポートしています。
    • ただし、テストのステップ定義は手動で記述する必要があり、コードの自動生成機能はありません。

https://docs.behat.org/en/latest/

  • PHPSpec
    • SpecBDD に特化したツールで、クラスのスケルトンやメソッドのスタブを生成する機能があります。
    • これは PHP 界隈では唯一実用的なコード生成機能と言えそうですが、完全なテストスイートを生成するまでには至りません。

https://phpspec.net/en/stable/

  • Codeception
    • フルスタックのテスティングフレームワークで、 Laravel との連携も強力です。
    • BDD(Gherkin)もサポートしていますが、こちらも基本的なテンプレート生成にとどまります。

https://codeception.com/

Ruby(RSpec) や JavaScript(Jest, Cucumber.js) のエコシステムと比較すると、 PHP の BDD 関連コミュニティは小規模で、ツールの進化も緩やかなようです。

では上記のような状況で、ライブラリ選定をするならどういう判断が良いか?

現時点では、Codeception に Laravel モジュールを組み合わせる方法がドキュメントも充実していてベターのようです(by Claude)。
もしくは、 Pest と共に pest-plugin-gwt を導入し、 Given-When-Then 形式でテストを記述するのも良さそうです。

いずれにせよ、現状では仕様からテストコードを全自動生成というよりは、 BDD の考え方を取り入れつつテストコードは手動でしっかり書くというスタイルが現実的なようです。

そういった技術的に自動化するのが難しい場合は、 feature ファイルとの連携が切れてしまうので BDD の思想からは外れてしまうのですが、今だと AI の力を利用させてもらうのが良さそうですね。
実際に何回か試してみましたが、簡単にテストコードを生成してくれました。

ビジネスチームを巻き込むには?

ここまで BDD の具体の活動を述べてきましたが、 BDD 成功の鍵はいかにビジネスチームを巻き込むかに尽きます。
「The BDD Books」では、ビジネスチームが参加せずに BDD のプロセスを踏むことを明確に悪手であると記述しています。

個人的にはそれは理解できるものの、では具体的にどうするのが良いのか会社ごとに状況が変わるので率直に言って難しいな...と思いました。

ただ、一応、本の中にもヒントは記載されています。

  • いきなり「BDD やります!」と言わない
    • ツールや方法論の話から入るのではなく、「仕様について、いくつか具体的な例を教えてもらえませんか?」と問いかけることから始める。
  • 相手のメリットを提示する
    • 「これをやれば、プロダクトオーナーのレビュー負荷が減りますよ」「開発者の手戻りが減って、その浮いた時間でより多くの機能開発に時間を使えるようになりますよ」といったメリットを伝える。
  • 成果物を見せる
    • 読みやすいシナリオをいくつか作成し、「こんな風に仕様をドキュメント化できます」と見せてみる。

上記に加えて私は、普段の行動から誠意を持って接して信用貯金を貯めておくのが良さそう、と思いました。

まとめ

ここまで「The BDD Books」を読んで学んだことをまとめてきました。
本書でも述べられていましたが、 BDD はすべての問題を解決する魔法の杖ではありません。あくまでチームのコラボレーションを促進するためのフレームワークです。

いきなり全部やろうとすると、おそらく挫折します。なのでまずはできるところから始めてみようと思い、2025年7月現在、実際に少しずつ行動に移しています。
最初のステップとして、私は取り組みの味方を増やすためにまずは開発メンバーで「実例マッピング」を試してみてます。
(ビジネスチームのメンバーが不在なので、本書で言う所の悪手ではあると思いつつ、スモールスタートをするためにあえてです)

最終的な目標は、 Gherkin でテストを自動化することかもしれませんが、その前にやるべきことがたくさんあると感じます。
まずはチームの対話の質を高め、仕様の認識齟齬をなくすこと。 BDD の本質はそこにあるのだと、今回の読書を通して感じました。

Discussion