AIIT夏合宿に1日だけ参加し、TDDを紹介して、みんなでペアプロをしてきました。大学生って若いんだなあ。 #enpit

途中から参加者を放置して、メンターの太田さんとペアで書いた、HTML Canvas版ライフゲイムです。最低限ですが、ブラウザ上で動きが見られるところまでたどり着きました(本当に最低限なので、見て驚いてください)。
https://github.com/yattom/tdd_life_javascript

さて、このコードのキモは3つあります。

1.テスティングフレームワークがない。フレームワークの使い方ではなくテストの書き方、考え方に集中するために、その場でテストのロジックを書き、それが関数になり、実行の仕組みを作り…と、テスティングフレームワーク自体を育てていくアプローチをしています(最近のお気に入り)。必要最低限の「フレームワーク」ができて手頃ですし、「これ面倒だからフレームワークで対応したい」というペインポイントを感じながら作れるのがメリットです。

2.テストコードとプロダクトコードが渾然一体している。1ファイル(life.js)にテストコードとプロダクトコードが入り交じった状態で進めました(パターンになかったっけ)。最終的には、テストが「上のほう」、プロダクトコードは「下のほう」にまとまっています。これは配置だけの問題でなく、プロダクトコードの中にテストのためのコードが入り交じっているという状況も作り出しています(例: セルを描画した回数をアサートするために、プロダクトコードの中で数える)。この件は次のキモにつながり…

3.モック(テストダブル)を嫌う。Canvasに描画するという処理そのものをテストするのは困難です。そこでモックライブラリを導入して、描画処理が何回呼ばれたとか、正しいパラメータが渡されているとか確認するのが、常道です。しかし今回は(2.で触れたように)プロダクトコードのロジックの中にテスト用の処理(何回呼ばれたか数える)を埋め込んでいます。大変だ!プロダクトコードがテストで汚染された!

ですが、TDDであれば、あるいはTDDでなくても、プロダクトコードと自動テストとが一体となって作られ、一緒にコミットされ、変更やメンテナンスも同時です。プロダクトコードとテストコードの意味的な分離はそれほど、昔ほどは重要ではないように感じています。今回実際に書いてみて、このくらいなら複雑にもならないし、可読性も悪くないし、扱いやすいコードにできることがわかりました。少なくともモックを導入するよりは、プロダクト+テスト全体としてシンプルになっています(実際の比較はしていませんけれど)。

もちろん、たかだか2時間で書いたコード量ですから、これから質・量ともに増えて複雑になっていけば、いつまでもモック不要とはいかないでしょう。一方で、プロダクトコードとテストコードの分離が絶対である、依存関係は一方通行であるというのは、ルールと言うよりはガイドラインに過ぎず、バランスやトレードオフを考えるべき条項なのではないでしょうか。

P.S.
Jim Coplienがセミナーで言っていました。「製品にアサートを(テストと言うよりはDbC的な表明だと思う)を埋め込んだまま出荷すべきと意見したが、止められた。なので会社を辞めた」。またハードウェアはたいてい、異常時にテストする仕組みを埋め込んでいます(内部の自動テストや、外部からテストする端子など)。