「何をすることでTDDをした」と言えるのか

東口和暉氏(以下、東口):2021年に読んでいるからこうなっているのかなって思っていました。TDDのなんらかのカンファレンスでキョンさんがTDDの事前設計っていう話をされていて、そのときにTDDの事前設計って何なんだろうとGoogleで検索して結果がでなかったんですけど。TDDの事前設計って何ですか? 

kyon_mm氏(以下、キョン):ちょっと待って。検索をしましょう。見つけたのは最近ですか?

東口:見つけたのは1年前か2年前です。

キョン:TDDBC Nagoyaのやつか?あったあった!

東口:ありました?

キョン:自分が書いた文章だから画面に貼り付けちゃおう。これ2014年1月7日だからTech Talkの直前のメーリングリストですね。

東口:そうです。これ! この文章です。

キョン:読み上げると、「何をすることでTDDをした」と言えるのかをハッキリさせたいということでした。RED→GREEN→REFACTORを回せればTDDをしていると言えるのか。事前設計をどの程度すればTDDをしていると言えるのか。60秒以内にRED→GREEN→REFACTORを回せればTDDをしていると言えるのか、みたいな。

東口:それです。TDDしているとは何ぞや? という議論の過程です。

キョン:思い出しました(笑)。事前設計っていうのはまさにプロダクトの設計ですね。『TDD by Example』の中に書かれているのは、TODOリストを書いて、そしてブレイクダウンして、ブレイクダウンした1個目をテストコードに落としてみましょうというTDDのファーストステップな進め方です。

そのときにプロダクトコードの設計がノーイメージな状態でやるのかどうかですよね。東口さんのレベルになると、TODOリストを書いている時点でどんな構造にしていくとか、どんなプロトコルにするかというのが頭の中にあるわけじゃないですか。

東口:あることにします(笑)。

キョン:複数人でやるときは確実にあると思うんですね。「こんなインターフェイスでさ」みたいな会話をすると思うんです。タスクのかたまりにおいて、テストコードを書き始める前にどれくらい設計していればTDDしていると言えるのか思って。

例えば先ほどの割引のテストをしましょうと言ったときに、何というクラス名にするとか、何というメソッド名にするとか、どういった引数の順番にするとか、引数名は何にするとかということを、TODOリストを書いているときにどれくらい考えるのかということですね。

きちんと考えていればかなり明確にTODOリストを書けるけれど、テストコードの1行目を書き始める前になにも考えていなかったら、ぜんぜんブレイクダウンできなくて、TODOリストは割引率を計算する1つだけになっちゃうと思うんですよね。

クラス名など考えるというのは一例ですけど、TDDを一緒にやろうとしているメンバーたちやユニットの人たちが、どの程度その問題を理解して、どういった構造で問題を分解しようとしているのかっていうのはTODOリストの分解でも垣間見えるし、頭なりホワイトボードなり、TODOリスト以外のところにもあるだろうという。

東口:前もって頭の中にもっているイメージとか、設計とかドメインモデリングを起動している場合だったら、「こういうドメインコードだよね」だったりとか。そういった開発までのイメージを事前設計と表現していたんですね。

キョン:そうです。

東口:1年越しにこの事前設計という4文字について理解ができてよかったです(笑)。

キョン:そうなんですよ(笑)。

今はプロダクトコード側の設計で言いましたけど、もうちょっとTDDやATDDという文脈で言うと、まずテストクラス名とか、テストメソッド名とか、テストメソッドの中における1行1行の書き方ですよね、とかもこれ(事前設計)になるわけですよ。

実際にテストコードとして何を表現しようとしているのかというのはまさにアプリケーションドメインにおける事前設計や分析行為なんですよね。

それの写像をした別のものがプロダクションコードにおける設計というところなので。事前設計は、プロダクションコード側だけではなくて、エンドユーザー側やそのクラスを使うデベロッパーという立場においてのドメインということですよね。

コードであったりプロダクトのUIだったりを触る人においてのドメインというものがテストコードに表現されるわけで。私たちはそこをどの程度考えてTDDに1行目を書き始めるのかっていうところが、それはTDDできているのかっていう問いにつながっていますね。

なにも考えずに、例えばテストメソッドもTest()でも、変数もvar hoge = calc() でもできるわけじゃないですか。でもそうじゃないでしょっていうのがあるんですよね。

東口:確かに。

キョン:となると、お客さんから言われた要件や、自分が分解したTODOにおいては、どんなテストメソッド名にするかとか、どんな変数名にするかとかもう設計が入っているんですよ。それをまったく考えずやっていても果たしてTDDと言えるのか。

ある程度こういった名前づけにしようとか、こういったメソッドの切り方をしようとか、これくらいのスコープにしようというのをやっていないと、TDDをやっているとは言えないんじゃないかとこのとき考えていたんですね。

よいBDDは「恋人を説明するとき」と同じ

キョン:事前にこれ話せたらいいねというネタリストのうち、なんと3割ぐらいしか終わっていないですね(笑)。

(一同笑)

東口:3割しか終わっていない感じですが、aki.mさんがDiscordで良いBDDのメタファーという話をされていて、「恋人を説明するときのように書かれているというメタファーを使っていたのが印象的だ」と言っていたんですけど、これはどういう感じですか? 

キョン:これは前に書いたんですよね。ちょっと待ってくださいね。自分のブログにリンクがあった気がする。昔、@ITで連載を書かせてもらった時期がありまして……あった。ちょっと画面共有で出しますね。

東口:なるほど。

キョン:「『振る舞い』とは何か」ということを、いろいろな書籍の「振る舞い」という単語から引っ張ってきました。Dan Northは「振る舞いとは、アジャイルにおける『要求分析』と非常に近しい」と言っていて、『レガシーコード改善ガイド』では「ユーザーの操作によって"実行"されるソフトウェアの"処理"であり"機能"である」と書いています。

『実践テスト駆動開発』では「システムの振る舞いは、オブジェクトの組み合わせから現れる性質」であると言っていたり、Martin Fowlerは「リファクタリングをしやすくするためのテストが振る舞いを書いている」と言ってたりします。

自分は「振る舞いの反対語は静的な構造、静的な仕組みだと思っています」と(連載で)書いたときに、じゃあ振る舞いのテストをできている、ビヘイビアのテストを書けています、書けていませんというのはどういうことでしたっけ? という疑問がありました。GOOS(『実践テスト駆動開発』)には「振る舞いのテストを行え、メソッドをテストするものではない」という言葉が書いてあるんです。

aki.mさんがDiscordで言ってくれていたのは、これですね。

boyFriendがnewされてmaryがいて、mary.walkでwith:boyFriendでmary is WALKINGしているとか、mary.stop()を送ったらmaryはSTOPPING状態である。適当なテストコードがあったとしてこれは悪い例として書いています。

良い例は、boyFriendがいてmaryがいて、mary.walk(with:boyFriend, weatherSUNNY).stop(because:RED_SIGNAL)で、mary.face is SMILE、mary.squeezeHand is boyFriend.hand。こうするとmaryがどんな人なのかがわかるんですね。

これはこの信号を送ったらmaryがこうなりますというだけなので、maryを実装したいと思って要求を書くときには、こうは書かないんですよね。例えばみなさんの家族や大切な人を説明する瞬間をまず思い浮かべてください。TDDの場合はどんな説明をしますか?

私の彼女は笑顔ができます、私の彼女は歩くことができますとは言わないですよね。こんなふうに歩いて、こんな顔で、こういうときにこんな表情をする人なんですよとか、こんなことをするとよく笑って、こういうことをするとちょっと苦い顔をして、そのときはこういったことがあって……みたいな話をしますよね。それが人における振る舞いじゃないですか?

端的に言うと、それが下の(良い)例で、上の(悪い)例はそうではない。(悪い例は)メソッドをテストしていて、(良い例は)振る舞いをテストしているという話ですね。

東口:なるほど。この(記事の)下のほうに出てくるテクニックとしてテストメソッド名を表現するというところにつながってくるんですかね。

キョン:そうですね。RSpecでやるともうちょっといろいろな記法が使えるので、ぜんぜんこういうものを使う必要はないんですけど、クラス名はコンテキストを表現するようにしましょうとか、When〇〇で何をするときとか、どんな状況かとか。例えばJUnitでやるとこうですよねとか、test〇〇()よりはshoud〇〇()みたいにとか。

こういった命名の方法が、ある種アプリケーションドメインを表現していて、そういったルールを使っていくことによって、振る舞いとしてフォーカスしやすくなっていきますよね。

東口:なるほど。恋人の話はこの記事だったんですね。

キョン:そうですね。『BDD in Action』に詳しく書かれていますね。『BDD in Action』も良い本です。

東口:電子はないんですね。残念ながら。

キョン:Amazonでは売られていないだけで、ManningからはPDFで買えますよ。Manning系の本はManningで買うと、KindleやPDF、EPUBも手に入ります。

東口:本当だ。

ATDDとBDDに明確な違いはない

東口:ちなみにこのBDDの話題の中で「ATDDとBDDで何が違うの?」という質問を7回ぐらい見たんですけど、実際根底としてすごく違うという感覚はあるんですか?

キョン:ないですね(笑)。

東口:「アジャイルテスティングなどいろいろな本での定義の違いは何?」って絶対カンファレンスで質問されるので、調べたり各書エキスパートの意見を見たりしても、記法のありなしぐらいでしか語られていなくて。

キョン:ATDDは、名前のとおりアクセプタンステストなので、自分たちのプロダクトを提供する先に対してのアクセプタンステストであるかどうかだと思いますね。個人的にはBDDとTDDはあまり違いがないと思います。やっぱりBDDは基本的に「TDDは、まずユニットテストを書くところでしょ」みたいなところに対するカウンターカルチャーが出発点なので、そこから生まれ出たフレームワークによる書きやすさという点では、非常によいところがありますけど。

私は、ツールはいったん抜きにして、概念としてこういったことをやっていこう、みたいなときにおける、TDDとBDDの違いは、実質的にほぼないと思っています。ツールやルールによって何にフォーカスさせたいのかというところが、BDDのほうがよりはっきりしているということですね。

その上で「TDDとBDDは何が違うんでしたっけ?」というと、フォーカスするポイントが違うぐらいで、特にTDDとBDDは定義としてテストのレイヤーの話をしていないんですよ。S/M/Lのテストのサイズの話を一切していなくて、『ATDD by Example』では説明しやすくするためにユニットテスト的なコードのテストサイズSの話をしていますが、あれは別にテストサイズがMでもLでもいいんですよね。

例えばRailsのコントローラーをnewして、とりあえず"Hello"が返ってくるHTTPか何かが範囲でも、別にそれはそれでいいわけですよね。なので、TDDやBDDは基本的にレイヤーをあまり考えていないです。TDDとBDDのユニットテスト向けだよねという考え方をした上でそれ以外のアクセプタンステストよりの部分がATDDとして際立ってくるという理解ですね。

東口:なるほど。それを図にしてみたんですけど、こんな感じですか?狭義のTDDがあって、BDDはカウンターカルチャーから始まっているもので、ここの違いはフォーカスしたポイントより、はっきりしたところ。そもそもテストサイズを考えていない広義のTDDがあって、強いて分けるなら、狭義のTDDはユニットテストにフォーカスしていて、それ以外というところで、こいつ(ATDD)とこいつ(BDD)はそんなに何か違いがあるかというと「まぁ……」という関係図で合っています?

キョン:合ってると思いますね。FitNesseなどはATDDのルーツになっていると考えられがちですけど、ルーツとしてはそうなのかもしれないんですけど、出発点が違う。その意味でいうとATDDとBDDはぜんぜん違う。

だけどそのフィット系のATDDとDan Northが提唱し始めたBDDは、ともに影響を与え合っていて、シナリオBDDとスペックBDDじゃないけど、どちらもBDDのツールと言われるようになった経緯があるので、現代的に捉えるんだったら、どちらもBDDでいいんじゃないかなと私は思います。

東口:なるほど。

キョン:出発は2009年の頃で、ATDDがFitみたいなものでアクセプタンステストもTDDするんだというムーブメントがありました。その上で狭義のTDDに対するカウンターカルチャーとしてDan NorthのBDDが生まれました。でもそのカウンターカルチャーとしてのBDDとATDDは、お互いに影響しあって成長していった経緯があって、結局どっちもBDDとしてのツールですよねと言われるようになったので、別にそれでよくない? というのが私の思いです。

東口:なるほど。2010年の時代で見たらおそらく違うんだろうけど、現代で見たら結果的に同じだと評価できるという解釈ですね。

キョン:そうですね。さらに言うと、この辺もすべてひっくるめて『SPECIFICATION BY EXAMPLE』とアジッチ(Gojko Adzic氏)がまとめちゃったので、もうそれでよくない? という気持ちはあります。

(一同笑)

東口:確かに。『ATDD by EXAMPLE』も実際すごく『SPECIFICATION BY EXAMPLE』の本にメチャクチャ影響を受けて作っていたことに鑑みると、実際その人たちも区別をつけようとしているかは、ちょっと違いますもんね。

キョン:そうですね。

(次回へつづく)