うさぎ組

ソフトウェア開発、チームによる製品開発、アジャイル、ソフトウェアテスト

TDD戦略 -TDDを導入し進化させる方法- #TDDAdventJP

@「TDDはスキルです。量は質に転化する」


TDD Advent Calendar2011の記事になります。
TDD Advent Calendar jp: 2011 : ATND
前:@ テストと言うパートナー #TddAdventJp - 日々常々
次:@ さんです。

はじめに

これは僕の主観であって、間違いもあると思います。それは僕の勉強不足から生じるものです。
どちらかというと、これを読んだ方に「そこはちょっと認識が一般的じゃない」「そもそも違うよ」って突っ込んでもらうためのものです。
「TDDよくわからないので教えてください」っていう記事です。

TDDをはじめたい人、TDDに行き詰まっている人

TDDがどんなものかよくわからない人、とりあえずテストコードって書いているけど毎回つまずいて成長が実感出来ない人、現場に導入したいけど伝え方がわからない人。
たくさんいると思います。
ということで、今回は僕なりにTDDについて整理してみて、TDDをうまく導入する方法、進化させる方法を考えてみました。

TDDの分類

まずはTDDを「書き始めるテストコード」で分類してみます。

次のようなスタイルで6つ紹介します。

  • TDDの名前
    • 書き始めるテストコード
    • 概要
  • オリジナルTDD(テスト駆動開発
    • 開発者の不安
    • KentBeckの「テスト駆動開発入門」に代表されるTDDの原点。TDDBCでもまずはこのTDDをベースに話をすることが多い。
  • BDD(振る舞い駆動開発)
    • 自然言語に近づけた上でのプロダクトコードの振る舞い
    • RSpecなどに代表される手法。読みやすいテストコードを目指していて、POやクライアントにも読み書きできることを目標にすることもある。
  • SATDD(ストーリー受け入れテスト駆動開発
    • スクラムなどの「ストーリー」に対する受け入れ基準
    • ストーリーの受け入れテストを先に書いてから詳細なプロダクトコードやテストコードを実装していく。
  • STDD(ストーリーテスト駆動開発
    • 対象アプリの具体的なストーリーやシナリオ
    • ユーザーシナリオなどをテストコードに表現する。シナリオテストと言われているものだと理解している。
  • UATDD(ユーザー受け入れテスト駆動開発
    • ユーザー(顧客)が行う受け入れ基準
    • ユーザーの受け入れテストをテストコードで表現する。ATDDの初出はUATDDの意味合いで出てきたけど、STDDが派生して、アジャイルの文脈でSATDDが出現してきたように見える。
  • VOTDD(検証指向テスト駆動開発
    • 開発者の不安+品質保証を主としたテスト手法
    • オリジナルTDDのリズムの中にテスト手法を考慮したテストコードを記述するフェーズを設けたもの境界値分析や原因結果グラフなどを用いた例を見たことがあります。


ここで注意してほしいのはSATDD、UATDDは僕が勝手に名前をつけました。
どちらもAcceptance TDDと呼ばれていてわかりにくかったので、
Story Acceptance TDD と User Acceptance TDD の二つに分けました。


どのTDDでも言えるのはRED->GREEN->REFACTOR のサイクルを作り出すことです。


TDDの特性

では、次にTDDを実施するときの観点について分類してみましょう。

次のようなスタイルで5つ紹介します。

  • TDDの観点の名前
    • 観点の要素の具体例
  • テストコードを書くタイミング
    • AssertFirst
      • プロダクトコード変更前に必ず失敗するテストコードを書く
    • 変更箇所対象切り替え毎
      • 次の変更箇所に移るまでには現在実装している箇所のテストコードを書く
    • 対象機能実装完了時
      • 現在取り組んでいる機能が実装できてからテストコードを書く
  • リファクタリングをするタイミング
    • Greenになったら
    • 変更箇所対象切り替え毎
    • 対象機能実装完了時
    • 嫌な匂いがしたとき
      • コードの腐敗臭がしたときにリファクとリングをする。詳しくはリファクタリング、レガシコード改善ガイド、xUnit Test Patternsを参照。
  • 網羅基準の厳密さ
    • 三角測量、境界値分析、原因結果グラフ、状態遷移など、どの程度まで厳密にテストコードに表現するか
  • 対象範囲
    • テストコードを書く対象をどこまで広げるか モデル、GUI、DB、通信処理など
  • モックやスタブの適用範囲
    • どこまでをプロダクトコード以外のモックやスタブとするか パッケージレベルでの境界、ネットワークレベルでの境界など

「テストコードを書くタイミング」ですが、個人的にはどれでもTDDだと思っていて、それは人の歩幅でしかないくらいに思っています。不安をテストにするという観点で言えば。

僕達は何をテスト駆動しているのか

TDDに限った話ではありませんが、自分たちが何をしているのか意識できていないときがあります。
ソフトウェアテストでは、「テスト戦略」というフェーズで「必要なテスト」「網羅基準」「時期」「リソース」「優先順位」などを定めます。
アジャイル開発で言われているように、優先順位をつけることが必要です。そのためにはまず全体を俯瞰できる必要があります。


同じようなことがTDDにも必要なのではないでしょうか?
TDDは楽しくて仕方なくってRED->GREEN->REFACTORのサイクルをずっと楽しんでしまって時間を忘れがちです。
でも、それでは「いつまでもリリースできない」「コストに見合わない品質」になってしまいます。
だから、戦略を立てましょう。それはとても簡素なものでもいいと思うんです。

TDD戦略という提案

「TDD戦略」として「TDDの種類」と「TDDの特性」を縦横のマトリクスにして、自分たちが取り組もうとしている開発手法を明確にしてみよう。
明確にすると、おそらく自分たちのTDDのパフォーマンスが測れます。
これはTDDの定量化につながりますし、基準を明確にすることは、他人に伝えやすくなることにつながります。
つまり、基準を決めるとTDDを導入しやすくなるんですね。


ということでGoogle Docsでマトリクスにしてみました。
[ファイル]-[形式を指定してダウンロード]でダウンロードできます。

Google Sheets - create and edit spreadsheets online, for free.




先に述べたようにここに記述したそれぞれについては不足しているものや間違いもあると思います。他の観点もあるでしょう。
なので、皆さんから活発な質問や意見をもらいたいです。
もちろん「こういったことはむしろTDDを衰退させる。誤解を招く」といったご指摘もあると思います。
皆さんが考えるTDDの効果や実情や未来について一緒に議論させてほしいです。

TDD戦略は成長する

TDD戦略は初めての分野の言語、フレームワークではなかなかたてにくいと思います。
なので、そのときはTBDとします。
そして1週間毎に振り返って、内容を更新しましょう。自分達がどれくらい現実に実行できているかで更新します。
必要だけど出来ていないのか、フレームワークの性質によって予測と違ったのか。
そして、また計画しましょう。
プロジェクトが終わる頃にはTDDという視座で対象のアプリケーションに有効な手段が見えているかもしれません。
あなたが不得意な分野が見えるかもしれません。
あなたのTDD戦略はTDDを導入する武器であり、自分のバロメーターでもあります。


完全にTDDすることが最終目標ではない

完全にTDDできることはなかなか少ないかもしれません。それは時間的な問題もあるだろうし、技術的な問題もあると思います。
もちろん出来る事もあると思っています。
そして完全にTDDすることの定義が僕にはわかりません。
仮に全てをAssertFirstでTDDすることが完全なTDDだとして、時間が無限にあったときにおいてそれをすることが正しいかは僕にはわかりません。


ただし、もし勘違いしてしまう人がいたら困るので、一つ言っておきます。
「大切なのは十分に品質のよいプロダクトをリリースすること」です。
TDD戦略のようなマトリクスをみたときに全てを最大にしてしまいたくなるかもしれませんが、忘れてはいけません。
品質を定義し、それに見合ったなかで網羅基準や手法や優先順位をつけてわかりやすくするためのマトリクスです。
そして、そのなかで最も効果的だと思うTDDを導入したり、発見したりするためのものです。



TDD戦略の経緯

ここからはもう惰性です。読まなくていいです。
TDDに基準やリズムなどを持ち込んでそれをうまく伝えたり、実施してもらうにはどうしたらいいかを考えていました。
また、僕も日常ですごく悩んでいます。
特に新しい言語やフレームワークをやりはじめて、しかも時間がないとどうしてもおろそかになります。


TDDBCに参加したり、どこかでTDDの話を聞くたびに「大切なのはリファクタリング」「テストコードに基準を」と言ってきましたが、自分でもうまく 伝えられているとは思えませんでした。どうしてもパッションでいってしまう。


僕は最近ソフトウェアテストの勉強をすることが多いのですが、気づいたんですね。あぁ、TDDを俯瞰すればいいのだ。と。
そして、このエントリー書いていくなかでTDD戦略という言葉が生まれました。
なので、TDD戦略は僕もまだ実施していません。だけど、すごくいいと思える。
今ある「TDDの分類」×「TDDの特性」っていうマトリクスでいいかはわからないけど、こういう方針があるとずいぶんと違うって思いました。
なので、実施してみて、どんどん進化させていきたいです。