テスト駆動開発/振る舞い駆動開発を始めるための基礎知識:いまさら聞けないTDD/BDD超入門(1)(3/3 ページ)
TDDの概要と進め方、目的と効果、歴史、さまざまな手法への展開、課題に加え、BDDの概要と種類、 重視される考え方などを解説する。
振る舞い駆動開発(BDD)とは
「振る舞い駆動開発」とは、TDDに触発されてDan North氏により提唱され発展した手法です。
BDDはTDDの一流派ともいえますが、TDDに対し以下の実現のための原則や工夫が加えられています。
- テストを「振る舞い」(機能的な外部仕様)の記述に特化させる
- ユーザーの要求やアーキテクチャの設計仕様といった、より上位のインプットとTDDのテストにつながりを持たせる
一例として、前述のアウトサイドインTDDもBDDの一種に該当します。なおBDDはTDDから生まれた手法ではあるものの、TDDで欠落しがちになったアジャイルのテストファーストの目的・原則に立ち返るという、原点回帰の方向性も備えています。
ちなみに今日のBDDは、いろいろな意味や定義で使われる用語になってしまっています。分類としては、テストレベルやテストベースのレベルを基準に、コードレベルとユーザーレベルの2つに分類されることがあります。
コードレベルのBDD
コードレベルのBDDは、「ユニットテスト」(単体テスト)や、コードレベルの結合テストといったテストレベルを扱う、プログラミングを駆動するためのBDDです。コードレベルのBDDはTDDの一種であり、主に以下に注意が向けられます。
- テストは、コンポーネントの振る舞いを記述するために書かれる(TDDではテストの目的は限定されていない。振る舞いだけではなく、作業達成のチェックなどを目的に記述されることがある)
- テストを書く際は、コンポーネントへの要求(コンポーネントがどのような振る舞いをすべきか)の特定を重視する。例えばテストファーストのサイクルに手を付ける前に、前述のアウトサイドインTDDのアプローチを使ってコンポーネント要求を明らかにするアプローチがしばしば採られる(一般的に運用されるTDDでは、前述のインサイドアウトTDDを許容することがある)
なおコードレベルのBDDのテストコードでは、振る舞いの記述に適したフレームワークを使用するのが一般的です。例えば、「RSpec」「CSpec」などのSpec系フレームワークや、「JBehave」などのBDDフレームワークがBDDでは定番ですが、それらは自然言語に近い構文でテストコードを記述できる特徴を持っています。
require './my_leap' describe MyLeap do it "should determine leap year if divisible by 4" do MyLeap.leap?(8).should be_true end it "should not determine leap year if divisible by 100" do MyLeap.leap?(200).should be_false end end
ユーザーレベルのBDD
ユーザーレベルのBDDは、受け入れテストやEnd-To-Endのシステムテストといったテストレベルを扱う、ユーザー要求や外部仕様の実現を駆動するBDDです。テストファーストの一種ですが、主に以下の特徴を持っています。
- ユーザー要求や外部仕様を、自動化された受け入れテストやシステムテストで記述する。テストの記述には、自然言語のようにテストを書けるセミフォーマルな言語や、ユーザーが可読できるドメイン特化言語(Domain-Specific Language、DSL)がよく用いられる
- アジャイル開発における「イテレーション」などの大きな単位で、テスト失敗→テスト成功のテストサイクルを回していく(テストサイクルを数十秒から数十分で回すプログラミング手法としてのTDDとは異なるスタイルを採る)
また、ユーザーレベルのBDDは、シンプルなルールや原則で構成されるTDDと違って、ユーザー要求をどう獲得・分析して、設計に導いていくかといったプロセスも包含した手法となっています。
ユーザーレベルのBDDで記述されるテストの一例を下記に示します。
Feature: ウェブページの表示と遷移テスト Google検索でウェブページの表示と遷移を確認します Scenario: Searching for test Given "https://www.google.com/"を開く When "test"を入力してボタンをクリックする Then "test - Google Search"というタイトルページが表示されること
ユーザーレベルのBDDでは、テストの記述に特定のフォーマットに合わせるセミフォーマルなアプローチが好まれます。
例えばアジャイルでは、しばしば「ユーザーストーリー」の形式でテストを記述します。テストの拡張性を重視する場合は「データ駆動テスト」や「キーワード駆動テスト」の構造をテストの記述に導入する場合もあります。
BDDで重視される2つの考え方
BDDでは、テストの記述において「Tests as Documentation」「Specification by Example」という2つの考え方が重視されます。
【1】「Tests as Documentation」(ドキュメントとしてのテスト)
「Tests as Documentation」はテストをドキュメントとして扱うアプローチです。テストの可読性を上げ、テスト対象の振る舞いを分かりやすく記述することにより、テストをテスト対象の詳細仕様書のように扱えるようにします。これはテスト対象の保守に活用されます。
【2】「Specification by Example」(例示による仕様)
「Specification by Example」は、例示による要求や仕様の記述を活用するための包括的な考え方です。例示を使って要求獲得や要求仕様化を行うことで、ユーザーとのコラボレーションや変化への対応、ユーザー要求と設計との関連付けを促進することを目的としています。
前述のTests as Documentationは、Specification by Exampleで中心的なアプローチの1つです。Specification by ExampleはBDDやATDDを支える、さまざまなプロセスを定義しており、BDDの基礎を支える考え方と位置付けられています。
次回から、BDDやアウトサイドインTDDについて具体的に
やや駆け足でしたが、TDDの発展や他への展開について解説しました。今後の連載では、今回挙げたBDDやアウトサイドインTDDについて、具体的な事例を用いて解説していく予定です。
関連記事
- テスト自動化の歴史と今後、良い/悪い事例〜システムテスト自動化カンファレンス2013レポート
テスト自動化を開発の“武器”にするための3つのポイントや、“自動化”の良い事例、悪い事例など、テストの現場を「進化させる」知見が多数紹介されたカンファンレンスの模様をレポートする。 - PHP開発者のためのテストのすゝめ(1):ユニットテストはなぜ必要なの?
開発の全工程の中で、あまり人気がないのがテスト工程だ。ソフトウェアの品質を証明するためのテストは、なぜ低く見られてしまうのか - Railsで目指せ、情熱エンジニア(5):なぜリファクタリングは必要なのか?
今回からいよいよコードの話を始めます。もはやRubyの文化の一部だという主張もあるリファクタリング、テストについて、その意義や概要を紹介します - Railsで目指せ、情熱エンジニア(7):Railsの人気テストフレームワーク6選!
前回は具体的なWebアプリを例にして簡単なコードレビューをしました。今回からは、テストを使ったリファクタリングについて解説していきます - Railsで目指せ、情熱エンジニア(8):実例で学ぶRailsアプリのテスト方法
前回はRailsで使われるテストフレームワークをご紹介しました。今回は具体的なWebアプリを例に、簡単なテストを使ったリファクタリングについて解説します - 第1回Androidテスト祭りレポート:Android開発で泣かないための「テスト」の重要性
その自由度の高さや多様性ゆえに、さまざまな課題を抱える、Androidアプリ開発の“テスト”に焦点を当てたイベントの模様を紹介します - UX Clip(28):JavaScriptのテストを開発工数に入れてもらうには?
Webアプリの大規模化とフロントエンド領域の拡大により、JavaScriptのテストの必要性が高まっている。数ある高機能なテストフレームワークをどう使いこなせば、高速かつ高品質な開発が可能になるのだろうか。 - テスト駆動開発はプログラマのストレスを軽減するか?
テスト・ファーストとリファクタリングの技法を組み合わせてプログラム開発を行う「テスト駆動開発」。簡単な例題を試しながら、この新しい開発手法を評価、検証する - 特集:Visual Studio 2008単体テスト機能徹底活用(後編):VS 2008単体テスト機能でテスト駆動開発/NUnitからの移行
VS 2008 Pro版に搭載されている単体テスト機能を使ってテスト・ファーストを実践。NUnitからのテスト移行についても考察。 - IT用語解説系マンガ:食べ超(3):テスト駆動開発で、みずから築いた壁にドーン
テストを書け! 話はそれからだ!
Copyright © ITmedia, Inc. All Rights Reserved.