近年、ソフトウェア開発においてアジャイル手法が広がっていく中で、人気が出ているのが「受け入れテスト駆動開発」(以下、ATDDおよびA-TDD)です。これらは一体どんな手法なのでしょうか? ここでは、その目的やメリット、アジャイル開発での意義、基本手順のほか、気をつけるべき注意点とデメリット、また従来のテスト駆動開発(以下、TDD)との類似点や相違点などについても解説します。
- もくじ
1.失敗と成功を繰り返しながら開発品質を高める「テスト駆動開発(TDD)」
今回の記事は「受け入れテスト駆動開発(ATDDまたはA-TDD:以下、ATDD)」がメインテーマですが、まず、その前に従来の「テスト駆動開発(TDD)」について簡単に説明します。
TDDとは「Test Driven Development」の略です。直訳すると「テストで駆動する開発」で、アジャイル開発の一種の「エクストリーム プログラミング 」(XP)から独立したものです。ちなみにXPは、顧客の要望を取り入れながら、要件定義から設計、開発、テストまでのプロセスを「イテレーション」という単位で繰り返し、品質を高めながらソフトウェアを開発していくアプローチです。
TDDは、動作する綺麗なコードを目標に、コーディング中の不安をコントロールするために開発された手法です。「自動化テストが失敗したときのみ新しいコードを書く」「重複を排除する」という2つのシンプルなルールがあります。
まず開発者は、コードを作成するより先に単体レベルでテストケースを作成しておきます。機能を定義した自動テストケースには、システム(ソフトウェア)が要件を満たせないような場合も意図的に設計します。テストを実施して、失敗した場合にコードを書き替え、再度テストを走らせ、すべてのテストが成功するまで変更します。
失敗と成功を繰り返しながら、生成されるフィードバックを通じて反復し、重複を除去してシステム品質を押し上げていきます。このTDDサイクルは「RED-Green-Rafactor」で構成されています。【図1】
【図1】「RED-Green-Rafactor」で構成されるTDDサイクル
2.「受け入れテスト駆動開発(ATDD)」はどのようなアプローチか?
では、今回のテーマである「受け入れテスト駆動開発(ATDD)」とは一体どんな手法なのでしょうか? 「ATDD」は「Acceptance Test Driven Development」の略で、文字どおり開発を駆動するものが「Acceptance Test」(受け入れテスト)になります。
受け入れテストとは、出荷判定の際に使うテストで、もし受け入れテストに通ったら、出荷してもよいという「リリース可否の証し」になります。
ATDDは、受け入れテストを最初にテストケースとして書いておき、内部プロセスでTDDを行うアプローチになります。ATDDでは、最終製品がどのように動作するのか、チーム内で明確なビジョンを示し、開発関係者全員のコンセンサスを取りながら進めていきます。
各担当がコード個々の記述で迷うことなく、目標に向かって集中して開発を続けられるようにサポートする狙いがあります。ユーザーのペルソナやストーリーなどに非常に役立ちます。
なお、受け入れテストについては、ユーザーを含めて誰もが理解できる自然言語で基本的に表現するケースが用いられることが多いようです。ATDDは、受け入れテスト自体が仕様になるため、最終的にテストをパスした段階で仕様を満たしたことになり、リリースすることができます。また、自動化された受け入れテスト要求をメンテナンスしながら繰り返し開発していくため、「実行可能な仕様」を実現することが期待できます。
ATDD はこうやって回していく! 理想的なATDDの流れと基本的な手順とは?
ATDDは、TDDと組み合わせて、入れ子のフィードバックループを回します。すなわちATDDは外側の大きなスコープ(外部品質)でのフィードバックループとなり、TDDは内側の小さなフィードバックループになります。事前に外側で失敗するテストを書き、内側(内部品質)のTDDサイクルでユニットテストを回していきます。【図2】
【図2】ATDDの代表的な流れ。ATDDは、TDDと組み合わせて入れ子のフィードバックループを回す。
【1】まず着手する要件や仕様(ATDDではuser storyという。使い手にとっての価値を記述したもの)を選びます。これが受け入れ基準となります。要件を満たす条件を、受け入れテストとして定義しますが、ここで失敗するuser storyの受け入れテストを書いておきます。
【2】次に失敗するユニットテストを用意し、小さなTDDサイクルの入れ子のループに入ります。ここで失敗するユニットテストを回していきます。もし失敗したらリファクタリングして、ユニットテストに合格するように再設計して実装します。
【3】ユニットテストに合格したら、次にuser storyの受け入れテストを回していきます。何回かこれらの外側と内側のフィードバックループを繰り返して回します。受け入れテストに加えて、過去に書いたすべてのフルリグレッションテストに合格後にリリースできます。
3.「ATDD」と「TDD」の共通点と相違点とは?
このようにATDDは、TDDを組み合わせたものになりますが、アジャイル開発において意義があります。ご存知の通りアジャイル開発は、短い反復で潜在的に納品が可能なシステムを迅速に開発するために使われます。
ATDDやTDDのアプローチは、前の失敗をベースにフィードバックを収集するという点で、アジャイルの原則に適う点が共通しています。システムを継続的にリファクタリングし、前の試行で直面した問題に対処するため、より価値のある最終製品の開発に役立ちます。このように2つの手法は密接に関連していますが異なる点もあります。
たとえばATDDには、プロセスに受け入れテストが含まれており、要求レベル段階からTDDの手法を取り入れたものであることが異なります。前出のようにTDDサイクルよりも、もう1つ大きなスコープでフィードバックループを駆動します。一番先にuser storyをテストコードとして定義しておき、それらをビジネス面で満たすように実装していきます。
TDDは、ユニットテストやコンポーネントテストをカバーするテストによって開発を駆動しますが、ATDDはビジネスフォーカスの強いテストによって開発を駆動します。またTDDよりもATDDのほうがチームのコラボレーションを重要視している点も異なりますので、これらの点を考慮して使い分けていくことになります。
なおTDDとATDDの位置づけを明確に理解するには「アジャイルテストの4象限」(Q1/Q2/Q3/Q4)という分類で考えると理解しやすいでしょう。これはテスト活動を2軸で分類したもので、縦軸に技術面とビジネス面、横軸に開発チーム支援(コーディング前に作成して欠陥防止)と製品批評(コーディング終了後に実施して欠陥発見)を取ります。【図3】
【図3】「アジャイルテストの4象限」の分類で、Q1がTDDの領域、Q2の領域がATDDの領域になる。
ここでQ1がTDD、Q2がATDDの属する領域です。つまりTDDからATDDを移行することで、技術面のユニットテストで駆動するTDDに対して、ATDDではビジネス視点の機能に対するテストの取り組みが強化されるのです。
4.「ATDD」のメリットとデメリットを整理してみる
ここまでATDDについて説明してきましたが、あらためて主なメリットとデメリットを整理すると、以下のようになります。
■ATDDの主なメリット
・最初にビジネス面での振る舞いを明確にするため、求めることに対する理解が進む
・受け入れテストが自然言語なので(ツールによる)、仕様が分かりやすく、漏れも少なくなる
・テストをパスした段階で仕様を満たすため、実装後に修正する事態が起こりにくい
・受け入れ側のフィードバックが迅速になり、要求側の不備の早期発見に寄与する
■ATDDの主なデメリット(注意点)
・決められた期間で課題を解決する場合と比べると、開発コストが増加する可能性がある
・受け入れテストの実装に工数がかかる(導入初期の学習コストなども含む)
・受け入れテストの仕様や機能をどこまで担保するのか、その粒度と範囲の決定に経験が必要
なお、受け入れテスト駆動開発で使われる代表的なツールもいくつか簡単に紹介しておきます。「Guage」「Cucumber」「FitNesse」などがあります。記法については特に規定されていませんが、自然言語で書くことが多いようです。
ツールによって「Cucumber」ならば「Given」「When」「Then」などのフレーズ、「Guage」ならばマークダウンでのシナリオ記述となり、「FitNesse」ならばWikiべースの記法なども使います。
まとめ
ATDDとTDDは類似したものですが、ATDDは、TDDを組み合わせて入れ子のフィードバックループとして使い、もう1つ大きなスコープでフィードバックループを駆動することでuser storyを実現していきます。
いずれもアジャイル開発という面で親和性が高いものですが、技術視点の機能を強化する場合にはTDDを用い、よりビジネス視点の機能に重点を置く場合にはATDDを用いるとよいでしょう。