見てわかるテスト駆動開発を見てのメモ
TDDBC基調講演のライブコーディングを見ました。
ずっとやりたいと思っている、でも工数ありないからできない、と思ってきたもの。TDDで開発すると何がすごいのか、本当に工数多くなるのか。
「テスト駆動開発」TDD考案者であるピアソンの書いたテスト駆動開発とは何かの本。t_wadaさん訳。
「動作するきれいなコード」テスト駆動開発のゴール
1. 重要なテスト, 2.テストが書きやすい(テスト容易性が高い)テスト
TDDでは2が優先される。が、TDDを極めてくると、1と2は一致する。
red → green → refactor
目の前の失敗するコードを成功するようにする。テストが成功するまま、リファクタリングする。
外部から見た振る舞いが変わらない→曖昧。対して、テストが成功する→0,1
リファクタリングのやめ時。→簡単なのは時間。時間が来たら止める。
FizzBuzz問題
面倒臭いなと感じるのは問題が十分に小さくないから。小さくしていく。
1 ~ 100 は複雑ではないけど、面倒臭い。1 ~ nまでできたら、100までできたとしていいだろう。後回し。
プリントする。仕組みが複雑な割りにテストできても嬉しくない。テスト容易性が低い。後回し。
日本語のブレをなくしていく。表現が合ってくると、問題が際立ってくる。重要なものとテスト容易性の低さは分離できる。
テスト容易性;低、重要度:低 にできる。プリントする。
1周目はテスト容易性が高い、小さく分離された物がよい。なぜなら、1周目は何もなく、重いから。
最初に「これは失敗するはず」とだけ出力するテスト→スタートラインに立てているかのチェック。テスティングフレームワークだったりeclipseだったり環境の問題が起きていたらこれは出なくて、いくらテスト書いてもダメなので、まずここをチェックする。
テストメソッドは日本語で(日本だけの開発の場合)。テストコードは動作する仕様書。可読性を高くしておく。
テストは準備、実行、検証、後片付け(Javaはガベージコレクションで省略)のステップになっている。テスト駆動開発では、検証、実行、準備の順に書いていく。単一のゴールをブラさずに書くため。
プログラミングの手が止まるのは残酷な瞬間。できると思ってた物ができない。具体的に考えられていなかったことに気づく。でもこれが検証フェーズとかになると戻りが大きくなってデスマーチになる。ここで突きつけられる、突きつけられるタイミングが早くなるのがTDDのメリット。
RED, GREEN, REFACTORのREDにコンパイルエラーも入る。
作る前に使う。作りやすいより、使いやすいの方が大事。まだ存在しないクラスを使う側の視点で使ってみる。
1周目は設計の意味合い強いので、重い。
次に、目の前の失敗しているテストを最短時間で成功させる。"1"をreturnする、最短の茶番。ひどい茶番の意図は、もし仮にこのテストが失敗したとしたらプロダクトコードにミスがあるとは思えない。とするとテストコードにミスがある可能性が高い。
テストコードにバグがあったらどうするの?→テストコードのテストコード書きます→ループ。。わざと判別可能な失敗を試すことで、テストコードをテストする。テストコードのテストにかかるコストが低いのも茶番のタイミング。
1周目は設計が重いので、実装を頭使わない物にする。
三角測量
assertを縦に並べる、or テストメソッドを不安。後者が推奨。assertを縦に並べるのは、失敗した時に、それ以降が実行されないし、最初の調査がデバッグから始まることになってしまう。→アサーションルーレットと呼んでいる。テストごとにアサーションは1つであることが望ましい。
new FizzBuzzが完全重複している。どこでアプローチするか。2アウト派、3アウト派→2箇所重複したらアウト、2箇所は偶発的なものだから3重複でアウト。
タスク分解が上手になるには、テスト容易性高いところと低いところが実装しているとわかってくる。設計の本を読んでみるのも、分解のしかたがわかって良い。両方やるのがよい。
テストが失敗している = リファクタはできない。→失敗しているテストを消して進める or 失敗しているテストを成功するように直す。
最短時間でall Greenに持っていき、リファクタリングする権利を得る。
前準備が重複しやすいというのはよくあること→@Beforeとかで各コードの前に1回ずつ実行されるコードがかける。
テストは上から順には実行されない。テストの依存性をなくすため。他のテストで作った変数を使ったりとかしだすとテストにならない。
より小さいリファクタリングに分ける。それによって安全にリファクタリングできる。
予想通りのタイミングで予想通りに失敗する→プログラマにとっては朗報。コンディションがよい。
TDDのスキル
・問題を小さく分割する。
・歩幅を調整する
・テスト→仮実装→三角測量→実装
・テスト→仮実装→実装
・テスト→明白な実装
ここまで前半。学ぶところが多すぎる。本当に面白い。
TODOリスト→ツリー構造。
クラスの中にメソッドを作成することで、クラス名には抽象度が高い情報を残し、メソッド名で具体例を残す、ということができ、仕様を未来の後輩に伝えることができる。
ツリー見るとなんかレベル感が合ってないぞ。→テスト名がよくないと気付ける。→クラス名を変更する。
テストにはメンテナンスコストがかかる。
読みにくいテストは不良資産になる。きちんと動作するドキュメントになっていないといけない。
TDDのスキル
・テストの構造化とリファクタリング
最後まで気が抜けないというか、過不足なく作られたセッションだった。分解するスキルというのはプログラミングに限らず必要なスキルだと思うので、設計系の本とか読みたいなと思った。時間がないとか理由つけてテストコード書かないことが多かったけど、きちんと書こうと思った。
あと、きちんと最後まで書けていないのが10年後の後輩の不良資産になるというのはよくわかる。コードもそうだし、コメント行とかwikiとかドキュメントも不良資産を見ることがとても多い。使ってから作る、というのはいろいろな場面で意識していきたい。
この記事が気に入ったらサポートをしてみませんか?