TDDBC仙台 the 3rdに参加してきました
10/12のTDDBC仙台 the 3rd行ってきました。
the 3rdということで、ルパンがお出迎えw
当日の様子は以下Togetterより:
http://togetter.com/li/576125
基調講演
TDD伝道師の和田卓人(@t_wada)さんの講演。
このイベントで何を勉強してきたか報告する場合は、
[動画で解説]和田卓人の“テスト駆動開発”講座
を見て下さいとのこと。
以下、講演の内容。
TDDの考え方
動作するきれいなコードへ至るための方法として、2通りの道がある。
従来は、きれいな設計をしてから実装していた。しかし、実際には実装を始めてみて気がつく問題が出てくる。そうなるとなかなか「動作する」の線を越えられない。
これに対して、汚い設計でもまず動くコードを作成し、それをリファクタリングしていくことできれいなコードにしていくアプローチがある。これがTDDの考え方。
ただし、このアプローチは「動くんだからもう直さなくていいだろ」と言われる場合があるので注意。
TDDのサイクル
この3つを真円に近づくように回すのが大事だと。
(JOJOは6部までしか読んでないので、黄金の回転分からんかった。。)
サイクルは素早く回すことが大事。対象を小さくして、一つずつ対処する。
時間がなくなってくると、Refactoringに時間が掛けられなくなり、真円から遠ざかる。
(思い当たる事が多々。。)
作る前から使う
作る前から使うことで、使う側の視点(使いやすさ)が得られる。
作ってから使うと、作る側の視点(作りやすさ)になってしまう。
不安なところをテストにする。
getterやsetterに不安なところはない。
複雑なメイン処理など、不安を感じるところのテストを書く。
TDDのテストはプログラムのテクニックで、品質担保が目的ではない。品質担保が目的のテストは他で行う。
(今まで、TDDはクラスの単体試験のテストケースを先に書くことだと思ってて、何だか違和感があったのが解消されました)
TDDの目的は「健康」
コード、チームの健康を保つことがTDDの目的。
TDDを導入すると、テストの実装工数が2割程度増加、バグ残存率が7割程度減。
デバッグにかかる時間が短くなるため、トータルの工数は減る。
ピアソンのバカ!
TDDライブデモ
@i_takehiro さんと、@leecom さんによるデモ。
当日の課題はこちら。
TDDということで、まずはテストから書き始め。
以下は自分の記憶を頼りに書いてるので、実際のデモで書いてたコードとは違うかも。
public class RangeTest { @Test public void 閉区間から下端点3を取得できること() { Range r = new Range(3, 8); assertThat( r.getLowerEndPoint(), is(3) ); } }
上記テストメソッドを以下の順番で実装。
- assertThatを入力。
- 「どうなったらテストOKなのか?」ということで、テストOKとする条件の is(3)を書く。
- その結果を得るためのメソッド呼び出しrange.getLowerEndPoint()
- メソッド呼び出すためのインスタンス生成Range r = new Range(3, 8);
この時点ではRangeクラスは存在しないので、テストケースのソース中に出ているコンパイルエラーを除去するようにクラスを実装(というよりEclipseのCtrl+1メニュー任せの空実装)。
public class Range { public Range(Integer i, Integer j) { } public Integer getLowerEndPoint() { return null; } }
この時点でテスト実行。期待値3に対してnull返却されるためテストはエラーになる。
続いてメソッドを実装。ここで驚いたのが、
public Integer getLowerEndPoint() { return 3; }
という実装でテストを通したこと。
いや、そりゃテストは通るだろうけど、、、こんなコードで通すことに意味あるの?
と思ったところで解説が。
これは、メソッドの仮実装というやつで、テストケースが正しいことを確認することが目的。もしこの仮実装でテストが失敗するようなら、それはテストケースがバグってることになると。
納得。
で、仮実装を本実装にする、ではなく、次に別のテストを追加。
@Test public void 閉区間4_9から下端点4を取得できること() { Range r = new Range(4, 9); assertThat( r.getLowerEndPoint(), is(4) ); }
この技法を三角測量というそうです。
このテストを追加したら、当然もう仮実装のコードではテストをパスできないので、ちゃんと実装して、全てのテストがパスすることを確認。
それが終わったらリファクタリングして、テスト実行して、問題ないことを確認しながら進めていく。
TDDってどういうふうに進めてくのか分からんかったので、興味深く見させて頂きました。
昼ご飯
会場で弁当が用意されてました。うまかった。
実践
人世初のペアプログラミング。
言語はJava。
終わったら、作ったコードをGithubに上げようと思ってたけど、最終的に書いたコード貰うの忘れたな。。
何故実装中にGithub使おうと思わなかったのか、今思うと謎。
やってみた感想としては、どこまでテスト書くかが悩ましい。
最初のうちはテストパターンは結構手を抜いて書いてたら、仕様漏れが発覚。テストが足りてなかった。
で、その後、「これだけやれば大丈夫だろう」というレベルでテスト項目を追加したけど、テストパターン1つにつきテストメソッド書いてassert文書くのは、作業感がありすぎてしんどかった。
気持ちの問題とは言え、やる気が出ないコード書くのはしんどい。コード書くテンポも落ちてたし。
もう少しテストが簡単に書ける方法がないと、「サイクルを素早く回す」ことが出来ないな、と思った。
そういう意味で、今日Groovyチームが使ってたSpockはすごく興味ある。
(後日追記) JUnit実践入門見たら、@RunWith(Theories.class)で、入力値と期待値をパラメータ化したテストケースが書けることを知りました。勉強不足orz
課題は良くできた課題だったなと思う。
課題2に入ったところでで終了になったけど、もう少し進みたかった。
今回は色々な言語チームがいて、それぞれの言語での実装が見れたのは面白かった。
他の言語見てると、Javaってやっぱり冗長だな~と思うことしばしば。
equals(Object)とかhashCode()とか実装すんのが面倒で手抜いたら、レビューで@i_takehiro さんからしっかり突っ込まれましたw
来年はGroovyで参加してみたいな~。もっと勉強しなきゃだけど。
最後に
懇親会に参加できなかったのが非常に残念 (T T
講師の和田さん、主催者の @135yshr さんを始めとするスタッフの方々、会場を提供して下さったデータコム様、参加者の皆様、ありがとうございました!