TDDという名の幻想...

TDDは死んだ。テスティングよ栄えよ。 by DHH
http://d.hatena.ne.jp/yach/20140424#p1

【翻訳】TDD is Fun
http://diskogs.hatenablog.com/entry/2014/04/25/085112

を読んで思ったことをつらつらと書いてみます。

TDDはできれば、やったほうが良いのは確か？です。

しかし、実際の開発現場で全面的に採用するのは
ミドルウェア等の画面の存在しないソフトの開発以外では
ほとんどの場合、無益です。

なぜなら、TDDを採用すると開発時間が膨らむ、すなわち、開発コストが
膨らむからです。そして、ソフト開発では細かな仕様は変化していきます、
するとTDDではそれに合わせ、テストを修正していかなくてはなりません。

また、TDDで書かれたテストが全てのケースを抜けなく網羅できていること
は稀です、抜けは必ず発生します、だからといって、テストコードを
レビューしだすと、開発時間(コスト)が膨らみます。

TDDのもと、テストをしていたからといって、画面のあるソフトでは画面上で
のテストは全パターン、行う必要があります。TDDで書いたテストでパスした
からといって画面でのテストを省けるではありません。

テストコードにはテストを書いたorレビューをしたエンジニアが想定していない
ことは反映されません、

画面のある開発でのTDDには掛かるコストを上回るほどのメリットがほとんど
ないのです。強いて、メリットを上げれば、エンジニアが自分は開発でテストを
きちんと行っているという(錯覚かもしれない)実感をもてるというくらいでしょう
か？

TDDに向く、TDDの費用対効果が高い開発は画面のないソフトの開発、
あるいは画面上のテストでは全パターンの網羅が難しい箇所の開発等
です。

TDDを画面のあるソフトで全面的に採用しているプロジェクトは
開発予算が潤沢にある富豪プロジェクトかクライアントから
できるだけ多くのお金をいただくために工数を積み上げることが
前提の業務用システム開発かにほぼ限られています。

WEBサービスプロジェクト等でTDDを全面的に採用するのは
コスト面からみると冒険です。クライアントがあり、
クライアントがTDDに掛かる費用を全額負担してくれるなら
話は別ですが。。。

TDDやテスト・ファーストは趣味の開発や学生による納期や
工数を気にする必要のないソフト開発にはよいかもしれません。
しかし、予算や開発時間の限られる画面のある開発で全面的に
採用するのはほとんどの場合リスキーです。

世の中には学生気分のまま、TDDやテストファーストを当たり前
に考えていたり、啓蒙していたりする御仁がいらっしゃいますが、
TDDは当たり前という幻想は持たないor早めに捨てることをオススメ
します。

貴方がクライアントor経営者としてTDDによる２重テストのコストを
全額負担しますorできますか？

TDDがSIer等の開発現場で産まれ揉まれ実践されてきたテストを含めた開発
メソッドと較べて低コスト？で高品質を保証してくれるという幻想は
どこから来たのだろうか？TDDが会社・組織内で実績のある手法を棄ててまで
乗り換える価値のある開発手法とは思えない。開発エンジニアの能力頼みで
開発メソッドを碌に整備してこなかったプロジェクト・組織・会社では
即効性？及び効果のある開発手法なのだろうか？？？

駄文をお読みいただき、ありがとうございました。

注) 上記の文章での TDD="ユニット"テスト駆動開発 です、
　　学問の世界はしりませんが、国内外を問わず開発現場
　　での一般的な理解です。TDD思想登場時にTDD実践支援用
　　ユニットテストフレームワークが多数登場し、これが
　　TDDであるとその開発者が喧伝？したためにそうなって
　　います。

　　WikipediaでもTDD="ユニット"テスト駆動開発と
　　なっています。(明示されてはいませんが、そのように
　　しか読み取れません。)
　　https://ja.wikipedia.org/wiki/%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA

　　TDD(テスト駆動開発)は先ずテスト(ケース)をコードで書き、その後実装しながら
　　そのテスト(ケース)をクリアしていくという開発手法ですので、仕様はfix
　　されておらず流動的であることが前提の(ウオーター・フォール型以外の)開発に
　　おいてユニットテストならまだしもシステムテストや統合テストでそれを行うのは
　　リスキーを通り越して無謀？だと思います、システムテストや統合テストのテストコード
　　(仕様書?)による駆動は品質確保の観点からは無意味です、ユニットテストなみに
　　全ケースを網羅するなら別ですが、テスト駆動開発でなくてもシステムテストや
　　統合テストは最後に必ず行い想定されうる全てのテストケースをクリアしなくては
　　いけません、ユニットテストの範囲までシステムテストや統合テストで網羅するのか、
　　という問題はありますが。

　　解釈を拡大してテストコードを書いていなくてもテストを行っていればテスト駆動開発
　　と呼ぶのなら、どんな開発でも大なり小なりテストを行いながら進行しますので、
　　全ての開発がテスト駆動開発になってしまいます、でもそれをTDDとはいいません。

注) TDDを全面的に採用しても開発時間(コスト)が膨らまない、あるいは
　　微増で済むためには採用するプロジェクトの構成人員ほぼ全ての開発
　　能力が充分に高いことが求められます、実際の開発プロジェクトで
　　開発人員全てに能力の高い人間を揃えられるケースは稀です、
　　それが常にできる企業・組織はほんの一部です、開発現場
　　全ての中の数％にすぎません。

　　この数％をこの文章では無視しています。

　　この数％もしくは開発コストの増加(初期コスト・教育コストetc)
　　を覚悟してTDDを導入している企業・組織・プロジェクトでTDDを
　　実践するのは問題ないのですが、そうではない企業・組織・
　　プロジェクトで個人の判断で勝手にTDDを導入して「TDDは当たり前」
　　と力説？されても企業・組織・プロジェクトとしては困るわけですよ、
　　TDDはTPOをわきまえて行いましょう(企業・組織・プロジェクトの
　　流儀には従いましょう)。

注) Capybaraであったり、その他の上位テストのテスティングフレームワーク
　　をこの文章では否定していません。開発現場でこれらのツールはTDDと(常に)
　　セットで利用されているわけではなく、ほとんどの場合、TDDとは無関係に
　　テストの自動化のために利用されています、そして、テストの自動化とTDDは
　　は全くの別物です。
　　
　　テストの自動化は品質確保のために行うテスト時間の低減のために
　　採用されています。想定される全パターンの手動テストを繰り返す
　　場合に発生するコストと想定される全パターンのテストコード
　　(再利用前提)を書くコストを比較して、テストコードを書いて再利用
　　するほうがコストが掛からない場合にです。

注) TDDは不要とは書いていません、TDDには掛かるコストほどの
　　メリットが(ほとんどの場合)ないと書いているのです。

　　ユニット・テスト・コードのカバレッジの達成率とTDDを結びつけて
　　語られても困るんですよね。TDDで前提となるテスト・コードを
　　網羅性の高い抜けのないレベルで教育なしに自分でゼロから書ける
　　開発エンジニアをほとんどの開発現場ではまず揃えられません。
　　カバレッジ云々する以前の問題、その前提となるユニット・テスト・
　　コードが先ず問題で、書かれたテスト・コードがカバレッジ云々できる
　　レベルで書けていることをレビューする、場合によってはテスト・コードを
　　レビュアーが修正する必要があるし、そのレベルでテストコードを書けるよう
　　にする教育(コスト)も必要になります。更に、派遣や外注の方を開発人員として
　　プロジェクトに多く抱えているプロジェクトでは外注や派遣の方をそのレベルで
　　テスト・コードを書けるように育てても育てる側の組織に属する人間ではない
　　ので、プロジェクトが変わる度に教育(コスト)etcが発生します。実社会の
　　開発現場でTDDを実践するには上述したモノを含め、様々な？コストが掛かる
　　のです。

　　上にも書いたようにTDDをコストの増加なしに実践できるだけの
　　レベルに達しているエンジニアを多数抱え、TDDを実践している
　　会社・組織・プロジェクトはこの文章の対象にはしていません。

　　そのような組織でTDDを推進している場合には、そのまま
　　TDDを推進していってください。

　　大学など学問の世界？でTDDを持ち上げたり、崇拝？したりするのは
　　勝手ですが、自分を含め自分たちの周りがTDDをコストの増加なしに
　　実践できるだけのレベルに達しているエンジニアばかりだからといって、
　　TDDがリアルで当たり前という幻想をいだくのはやめてもらいたい
　　ところです。

　　TDDが有用であるというのなら、学術の組織内での研究ではなく、実社会
　　の中・大規模開発プロジェクトでTDDでない場合と較べてどれくらいのコスト
　　の増減があり、コスト面も含め、どのように有用であるかを示してもらいたい
　　ところです。学術の組織内という箱庭の中での研究結果(往々にして小さな
　　プロジェクトでの実践結果)で有用と言われても有用であるとはリアルでは
　　判断されません。

　　学問の世界で有用とされた開発手法で実社会からは無用とみなされた開発
　　手法は数多？あります。

　　実社会のプロジェクトであっても東大・京大の出身者等生え抜きのエンジニア
　　で構成された開発プロジェクトでの実践結果は現実の開発現場のほとんどでは
　　全く参考になりませんので。そのような例を出されても、TDDが有用であるとは
　　考えませんので悪しからず。

　　(言わずもがなですが、実社会の営利目的でする仕事には会社・組織・
　　プロジェクトからみると全てコストが掛かっています。そして、それは
　　ソフトウェアの開発現場でも同じです。掛かるコストに見合うメリット
　　のない開発手法は会社・組織・プロジェクトでは受け入れられません、
　　ある開発手法に掛かるコストに見合うメリットがあるかは会社・組織・
　　プロジェクト毎に判断されます。特定の会社・組織・プロジェクトが
　　その開発手法にメリットがあると判断したからといって、それが
　　他の会社・組織・プロジェクトにとってもメリットがあるわけでは
　　ありません。)

注) 少し真面目？に書いてみる。
　　DHHは『TDD≒Test Firstをやってきたけど、実装する前にテスト・コードを
　　書きそのテストに通る実装を書くのは、テスト・コードにmockが必要だったり、
　　実装への制約になったり、実装している最中により良い設計？を思いついた際に、
　　その方向で実装していくと後からテスト・コードの変更が必要になったりして面倒、
　　だから、これからはTDDをやめて「Implemantation first」「Test second」
　　「No(t) Test-less」な方向でいくよ、ユニット・テストをしないわけじゃない、
　　しっかりするよ、テスト・コードも書くよ、実装ありきだけどね。画面をテストする際
　　にはCapybaraとかも使ってるよ』と書いてるようにみえる、要約すると(超訳かも。。。)。

　　自分も「Implemantation first」「Test second」「No(t) Test-less」な方向で
　　いいんじゃないかと思ってる。
　　
　　個人的にはTDDのテスト・ファーストに抵抗感が、、、なので、TDDを強制する
　　環境では仕事したくない。実装(モノづくり)が目的なのであって、テストが目的の
　　わけじゃないので。(※個人の感じ方の問題です。)

　　自分は先ず実装してからテストしてるし、実装時間以上にテストに時間を掛けてる
　　こともままある、場合によってはテスト・コードも書いてる。
　　
　　テストは品質のために必要だけど、できれば、テスト時間(テストに書けるコスト)は
　　最小化したい、テスト・ステージ(ユニット・テスト、システム・テストetc)毎に
　　同じテスト・ケースを何度もテストするのはできれば避けたい。
　　
　　それに画面があるソフトウェアでは実装してから画面で確認(テスト)すれば済む
　　レベルのことまで、わざわざ全てテスト・コード化しておくのは不毛(と感じる)。
　　
　　多くのクライアントや利用者にとって品質はあって当たり前のモノ、最低限の品質を
　　クリアしていないモノは使ってくれないけど、品質に金を払ってくれるかというと
　　そうでもない、最低限の品質さえクリアしていれば、品質はそんなに気にしない。
　　大きな不具合があれば問題となるが、小さな問題ならクレームがつく程度、きちんと
　　対応すればノープロブレム。品質に必要以上にコスト(≒お金)を掛けても意味はあまりない。
　　例えば、日本の電化製品、品質は良いけど、海外では売れないよね、高品質のために掛けた
　　コストが全て製品価格に上乗せされてるから。
　　日本人技術者は高品質に価値をおきすぎ。

　　テストを全て？コード化するTDDにはコストが掛かるし、採用するプロジェクト・
　　組織・会社にはそのコストを吸収できるだけの体力？が必要。

　　そもそも短納期のプロジェクトを回している組織・会社ではTDDの導入に伴う
　　初期コストを掛けられない(吸収できない)場合が多い。(そのような会社でTDDに
　　即対応できるエンジニアを多数抱えていることは稀。)

　　TDDをやるだけの地力のあるプロジェクト・組織・会社で開発エンジニアに
　　先ずテストを書くことに抵抗がなければ採用し、上手くいけば、プロジェクト・
　　組織・会社で推進していけばいい。けれど、自分たちのトコロで上手くいった
　　からといって周りも全て上手くいくという幻想をいだくのはやめてもらいたい。
　　
　　それにTDDはSIer等の開発現場で産まれ揉まれ実践されてきたテストを含む開発
　　メソッド(プロセス？)との親和性が低い、というか、ない。プロジェクト・
　　組織・会社内で既に実績のある開発メソッドを棄てて乗り換えるほど大きなメリットは
　　TDDにはない。

注) 同じテストを何度も繰り返して行う必要のあるプロジェクトでのテスト自動化の
　　有用性は否定していません、しかし、レグレッションテストのためのテスト自動化
　　とTDDは全くの別物です。

　　レグレッションテストの回数が多い場合にはテスト・コード化するコストを手動テストの
　　コストが上回るので、テスト・コード化するほうが良いのは言わずもがなです。

　　そういう自分も https://github.com/asip/meteor にてレグレッションテストの
　　ためのテスト・コードを用意していたりします。demoの中にあるのがそれです、
　　テスト・コードとして利用しています、流した結果は目視で確認していますが。

　　TDDのメリットとされていることの全てはTDDだからできるという類のものではなく、
　　TDDでなくてもできるのです。TDDを絶対神聖化？する意味が全くわかりません。

　　コメントにて書かれている方もいますが、現在、WEBアプリではJavascriptの高速化
　　及びデバイスの高速化によりクライアントサイド(ブラウザ)でより多くの処理を行う
　　モノが増えてきています。UIまわりでは要素へのエフェクトの適用、要素の表示・
　　非表示等を行い、視覚的に魅せることが必要になってきたりもしています。
　　全ての主要ブラウザの挙動は全く同じという幻想をいだいている方もいらっしゃる
　　かもしれませんが、ブラウザ毎に微妙に挙動が異なるケースは多々あります、特に
　　UIまわりでは。UIまわりで色々とやっているWEBアプリでは主要ブラウザ毎にテストを
　　して目視で確認する必要があります。テスト・コードの自動化ではUIまわりの挙動の
　　チェックはできません。WEBアプリに限らず、画面のあるアプリでは画面の目視に
　　よる確認は必須となっています。

　　SIer等では既にTDDの評価は行なわれ、その結果、TDDを構成する個別要素のうち
　　有用なものは会社・組織内で作成・錬成してきた開発メソッドに既に組み込んで
　　います。会社・組織内で実績のある開発メソッドをTDDベースに置き換えるよりも
　　TDDから良い所どりしたほうが会社・組織にとって有益であると判断されているの
　　です。

注) 上の記事で「TDDが死んでいる」と書いていると誤解している人がいるようなので
　　追記しておきます。TDDが死んだ、とは思っていません。TDDはテストの強制が
　　できる点で意味があると考えています、とかく(自分も含め)エンジニアはテストを
　　なおざりにしがちなので。。。
　　
　　でもTDDをやるにはそれなりにコストが掛かる、実際の開発プロジェクトでその
　　コストを受け入れられる条件の整っているところは全体的にみれば案外少ない、
　　TDDを銀の弾丸・唯一絶対の特効薬みたいにいうのはやめようよ、という話です。
　　
　　TDD自体を否定しているわけではありません。TDDのコストを受け入れられる条件
　　の整っているところでエンジニアにテスト・ファーストに抵抗感がないのであれば、
　　TDDを採用し推進していけばいい、また、TDDのコストを受け入れられる条件
　　の整っていないところはTDDを部分的に採用して(＝TDDの構成要素のうち
　　プロジェクト・組織・会社にとって有益なモノを取り入れて)やっていけばいい
　　のではないか？と思っています。

　　(狭義の)TDDはテスト・ファーストを前提とした一枚岩の開発手法であると
　　理解しています。

　　今の時代、取捨選択のできない一枚岩の開発手法ではあらゆるニーズに対応する
　　ことは不可能なのではないでしょうか？
　　
　　はじめはTDDには向かないタイプの開発もあるよね、と書いていたのが、途中から
　　TDD自体に対する是々非々？みたいになってしまっています。。。

他) コメントに小規模ソフトウェアハウスの方？による、自分のところではTDDの導入
　　に挫折・失敗したこと、周りにもTDD導入の失敗事例があることからTDDは銀の弾丸
　　・唯一絶対の特効薬ではないような気がするとの書き込みがあったとき、それに
　　対してその方をけなす？ような書き込みがTDD信奉者？の方から書き込まれていました。

　　けなしていないにしても、相手の意図？を汲み取る努力を放棄し、自分たちの主張を
　　一方的に押し付けているようにみえました。

　　書き込まれた方は二度とTDD界隈には近づくまいと思ったはずです。

　　どのようにすれば上手くいく、例えば、TDDをはじめから全て実践するのではなく、
　　はじめはテスト・ファーストはせずに、他の構成要素を(部分的に)導入して、そこから
　　徐々にテスト・ファーストにもっていくとうまくいくよ等の、(TDDの導入に再トライ
　　してみようと思わせるような)建設的なアドバイスができたはずです。

　　TDD信奉者の方？は自分たちのところが特に苦労することもなく(※程度の問題です、
　　素養？のある集団であれば、ない集団に較べて、という話です。)上手くいったから
　　周り全てが苦労することなく上手くいくと錯覚しているように思います。

　　TDD信奉者の方？は自分(たち)を普通のエンジニアと思い、自分(たち)を基準に
　　しているのかもしれませんが、あなた方のほとんどは「３聴けば10わかる
　　３聴けばそこから自分で大した努力もなし？(※程度の問題です、素養？のある人
　　であれば、ない人に較べて、という話です。)に10にたどり着ける」人の
　　はずです。
　　
　　世の中、３聴けば10わかる３聴けばそこから自分で(努力して)10にたどり着く人
　　ばかりではないのです、10理解させるためには10教えなくてはならない(自分での
　　努力を放棄している、生活費を稼ぐ手段としてエンジニアをやっているだけ・
　　いわれた仕事をするだけで技術そのものに全く関心はない・勉強のために自分の
　　時間を使う気もない)人(くれくれ君？)、(既に習得した技術にしがみつき)新しい
　　技術の習得に消極的で前向きに取り組まない人もいっぱいいるのです。

　　素養？のある人(集団)とない人(集団)とでは開発手法等を導入する際に掛かる
　　コストに(大袈裟かもしれませんが)天と地ほどの開きがあるのです。

　　http://www.slideshare.net/t_wada/osh2014-sprit-of-tdd/44
　　にあるMS･IBMでの導入事例をTDD信奉者？の方が持ち出されていましたが、
　　導入結果と導入しない場合の数値による比較・被験者アンケートの内容、
　　導入から得られた知見についてしか触れられていません(被験者？集団の
　　構成や適用したプロジェクトの詳細については何も触れられていません)。
　　
　　MS･IBM等の大手IT企業は３聴けば10わかる、３聴けばそこから自分で
　　大した努力もなし？(※程度の問題です、素養？のある人であれば、ない人
　　に較べて、という話です。)に10にたどり着ける人の集団です。

　　この導入事例をみてTDDの導入に踏み切る人はいないのではないでしょうか？

　　TDDの導入を検討しているところは、どうやればうまくいくのか、
　　導入した会社ではどういう手順で導入していったのか、自分(たち)
　　のところで適用可能かの判断材料を知りたいのであって、導入した場合
　　と導入しない場合の数値比較等を知りたいわけではありません。

注) 趣味や学術研究での開発でもない限り、「テストにはコスト(お金)が掛かる」
　のです、「テスト・コードを書く」のにも、当たり前ですが。(学術研究であっても、
　それを仕事してやっているのなら、コストが発生しています。)
　
　テスト・コードは書けば終わりではなく、テスト・コードに対する動作確認も
　必要になります。それもまた、コストです。目視でテストすれば、一瞬で
　確認の終わる内容に対して、テスト・コードを網羅的に書いて、テスト・コード
　を目視でテストして、テスト・コードが通った後に本体を網羅的に目視で
　テストするのはコスト面で無駄な気がします。
　
　テスト・コードは万能ではなく、その作成・メンテナンスにコストが掛かる上に、
　テスト・コードを通ったらテスト終了ではなく、その後に目視でのテストは
　ほとんどの場合、必須です。　

　使い捨てのソフトや頻繁に変更の発生しないコードなら、目視でのテストで
　事足りるので、デグレを気にしてテスト・コードを書く必要はありませんし、
　開発中に仕様が変わり、書いたテスト・コード(の一部)を捨てることになったり、
　テスト・コードの大幅な書き換えが必要になることはザラにあります。仕様変更の
　場合、本体を修正し目視でのテストで動作を確認してから、テスト・コードを修正
　・テストすることになったりします。
　
　全てのケースでテスト・コードを網羅的に書くのはほとんどの場合、コスト面
　からみるとナンセンスだと考えています。開発者の自己満足のための網羅的な
　テスト・コードに対して誰がそのコストを負担してくれるのでしょうか？開発の予算
　に限りがある以上、開発に掛けられる期間にも限りがあり、その中でテスト・コード
　を書くのに掛けられる時間にも限りがあります。

　趣味のプロジェクトでもない限り、プロジェクトの予算が限られている以上、
　その中で品質を担保するために掛けられるコストは限られています。
　(趣味のプロジェクトであっても、趣味に掛けられる時間が限られている
　以上、その中で品質の担保に費やせる時間は限られています。)

　仕事としてのテスト・コード作成・メンテナンスを作成者が無報酬で徹夜
　してでもやってくれるのなら話は別ですが(趣味なら、網羅的にテストコードを
　書きたい方は自分の納得いくまで、時間を掛けて書けばよいと思います)。

他） TDDで開発者の安心とやる気が担保される、という主張はわけがわかりません。

　TDDが他の開発手法よりもトータルのコストが掛からないというのであれば、
　根拠となる実例を示して下さい、大学の研究室の実験での結果や趣味での結果は
　根拠にはなりえません。

　(今まで、テストがおざなりであったプロジェクトに本来のTDDを導入した場合、大概は
　プロジェクトが破綻すると思います、)

　TDDの根幹？は、「テスト・コードで品質を担保する」ことにあると考えてます。

　TDDの原典？には「テスト・ファースト」と明記されています。実装よりも先にテストを
　書き、そのテストを通る実装を書く、のが本来のTDDです。なので、TDDにおいては
　本来、テスト・コードを網羅的に書くことが前提であり、網羅的でない虫食いのテスト・
　コードでは、TDDの効力が半減どころか、TDDを実践する意味自体がないに等しいと
　思います。

　本来のTDDでは、テスト・コードの(品質・)網羅性がそのまま、実装の品質に直結します、
　テスト・コードの(品質・)網羅性が低ければ、実装の品質も自ずと低くなります。

　実装する前に必要なテスト・コードを網羅的に書けるエンジニアが揃っている
　プロジェクトが世界にどのくらいあるのでしょう？

　実装中にテスト・コードを実装にあわせて修正しているTDDプロジェクトは山程？ある
　のではないかとも思います。

　開発中に開発しているソフトやサービスの仕様がころころ変わるプロジェクトも山程
　あります。そのようなプロジェクトではTDDを実践するメリットよりもデメリットのほうが
　大きいと思います、他の方がすでに書かれていますが。

　テスト・コードを書くことで、安心する、や、やる気がでる、と感じている職業エンジニア
　は稀だと思います。品質を担保するために必要だから、クライアントの安心に繋がるから
　(クライアントから要求されているから)、テスト・コードを書いている職業エンジニアが
　大半ではないでしょうか？

　テスト・コードを書くことは有用だと考えています。ただ、コストが掛かるので、
　テスト・コードをどこまで書くのか(品質の担保をどこまでテスト・コードに頼るのか)
　を予め設定しておく必要があると思います。

　テストはテスト・コード(だけ)に頼るのではなく、手動でのテストを含め、(コスト面を考慮
　した上で、)トータルで考えるべきモノだと思っています。