jjug ccc 2014 fall ...
DESCRIPTION
2014/11/15 JJUG CCC 2014 fall 「私がTDD出来ないのはどう考えてもお前らが悪い!」~エンタープライズJava開発でのTDD適用の勘所~TRANSCRIPT
#ccc_r11
私がTDD出来ないのはどう考えてもお前らが悪い!
~エンタープライズJava開発におけるTDD適用の勘所~
2014/11/15
大中浩行
#ccc_r11
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
突然ですが、TDDとは?
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
TDD三原則 (Uncle Bob)
• 失敗する単体テストのコードを書く前に、製品
のコードを書いてはいけない
• コンパイルが通り、適切に失敗する単体テスト
が通るまでは、次の単体テストを書いてはなら
ない
• 現在失敗する単体テストが通るまで、次の製品
コードを書いてはならない
「Clean Code アジャイルソフトウェア達人の技」
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
という原則は原則として踏まえた上で、現場に
TDDを導入するときに何を考え、どう行動した
かというのが今日のテーマです。よろしくお願
いします。
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
アジェンダ
• なぜTDDするのか
• どうTDDするか
• 技術的な各論
• なぜTDDするのか(again)
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
• 大中浩行(Ohnaka,Hiroyuki)
• TDDBC横浜(2011~2013)主宰
• yokohama.devtesting / devtesting-ja
• #agilesamurai #横浜道場
• Twitter @setoazusa
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
• グロースエクスパートナーズ(株)
• 大手通信事業者の法人向けサービス開発プ
ロジェクト
• TDDの導入、DevOpsの推進、プロジェク
トメンバーのフォローなどがお仕事。
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
アジェンダ
• なぜTDDするのか
• どうTDDするか
• 技術的な各論
• なぜTDDするのか(again)
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
「テストがないコードはレガシーコードだ!」
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
「いまさら聞けない」
http://www.atmarkit.co.jp/ait/articles/1410/17/news034.html
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
各所で猛威を振るうt_wada.png
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
テストを書かなければプログラマーにあらず?
その一方で…
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
TDD is dead.
http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
「TDDを諦める」
http://takashiba-labo.hatenablog.com/entry/2014/10/17/003431
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
「テスト駆動開発はなぜ流行らなかったのか?」
http://peace.2ch.net/test/read.cgi/tech/1389568154/
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
どうしてこうなった
• もともとTDD(というよりアジャイル開発)に
関連するプラクティスはそれぞれが密結合し
ていて、TDD単独で理解するのが難しいとい
うのはありますが…
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
「テスト」と責任の関係
• テストという工程は、その性格上、品質保証
や、成果物への責任と強い関係をもっている
• 「テストを書くべきだ」という論に明快に異
を唱えられる人は少ない
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
• 開発プロセスの望ましい姿を論じていたはず
が、道義的な責任の問題になってしまう
• テストを書く人と書かない人の間の感情的な
対立は、何も生み出さない
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
「TDDやれば偉いわけじゃない」
http://b.hatena.ne.jp/entry/232721484/comment/t-wada
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
総合力の必要性
「テストを書く」ということは、CIや静的解析、
コードレビューやペアプロなど、チーム開発の
ためのプラクティスと連携して、初めてその力
を発揮する。
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
では、なぜTDDするのか
…?
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
一つの答え
• 「動作するきれいなコード」のために
「テスト駆動開発入門」
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
テストファーストにこだわらない
• 表層的に、テストを先に書くかどうかではな
く、テストを書くこととプロダクションコー
ドを書くことが統合されているか
• そして、テストが開発の助けになっているか
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
アジェンダ
• なぜTDDするのか
• どうTDDするか
• 技術的な各論
• なぜTDDするのか(again)
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
プロジェクト概要
• 大手通信事業者の法人向けサービス開発
• メンバー 開始時11名→現在21名
• 開発プロセスはスクラム
• サービスインまでの開発期間7ヶ月
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
プロジェクト概要
• Backbone.js(CoffeeScript) + Spring MVC
+ Spring Batch + Hibernate(JPA)
• ユニットテスト総ケース数3800ケース
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
立ち上げ時の状況
• クライアントの開発部隊+インテグレーター
2社で1チーム
• 初めて顔をあわせるメンバーが多い
• とにかく手探り
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
ペアプロ
• ペアを組んでユニットテストのコーチング
• とことんつきあう
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
テストファーストにこだわらない
• イテレーションの中で実装とテストが完結し
ていれば、テストファーストでなくてもよい
ことに
• テストがあることのメリットを実感してもら
う
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
ユニットテストを過信しない
• フェイルファストしてないユニットテストが、
しているテストと比べて信頼性を欠くのは事
実
• 自動でないテストも重視
• ユニットテストから漏れるバグがあることを
受け入れる
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
全部をテストしない
「サーバーサイドはばっちりテストを書きます。
フロントエンドも自動テストして、end to end
のテストもSeleniumで自動化します」
「落ち着いてください」
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
• まずはサーバサイドのユニットテストの整備
から
• サーバーサイドはAPIのエンドポイントとな
るController/Serviceクラスについてはテス
トを網羅
• 後は必要に応じて
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
100点を目指さない。優先順位をつける
ユニットテストの5つの規則(F.I.R.S.T)
• 再現性がある (Repeatable)
• 独立している(Independent)
※ほか、高速である(Fast)/自己検証可能(Self-Validating)/適時性(Timely)
「Clean Code アジャイルソフトウェア達人の技」
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
スキル・ノウハウの共有
• スプリントごとにペアプロのペアを組み替え
• アトラシアンフルスタック
(JIRA/Confluence/Bamboo/Stash)による
情報共有
• 「伝言ゲームソリューション」
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
しかし問題も…
開発が進むにつれ、たまっていく技術的負債
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
技術的負債
• 意図がはっきりしないテスト
• テストメソッド名とやっていることが一致しな
いテスト
• コピペ
• モックの使いすぎ
• etc…
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
技術的負債の返済
• 改善サイクルをまわす
• スプリントごとの振り返り(KPT)
• Tryをちゃんとタスク化する、工数を割り振
る
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
結果
• リリース判定会議をスムーズにクリア
• リリース直前に殆どのメンバーが定時帰り
• サービスイン後も定期的にリリースを実施
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
どうしてうまくいった?
• RESTfulのAPIを定義した上で、フロントエンド
とサーバサイドでそれぞれ実装して、それを結
合するというプロセスだったので、ユニットテ
ストでサーバーサイドの動作を確認するという
アプローチが自然だった
• Controller層とService層もModuleを分割してい
たので、同じ事が言える
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
「信頼で結ばれた共同体」(※)
• 「2人目」の存在
• 問題を指摘するとちゃんと次のスプリントに
のせてくれる
• 人対人でなく、問題対私たち
• 「いいもの」をつくるという合意※「組織パターン」から
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
アジェンダ
• なぜTDDするのか
• どうTDDするか
• 技術的な各論
• なぜTDDするのか(again)
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
お品書き
• スローテスト
• データベースを使うテスト
• Controller層のテスト
• モック
• フロントエンド
• End to Endのテスト
• 作業をテストする
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
スローテスト怖い
スローテストによる開発リズムの悪化
→ビルドの通らないコードのpush
→CIの信頼性低下
→デリバリーのフロー崩壊
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
よくあるスローテスト対策
• 組み込みデータベースを使う
• データベースをモックする
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
だがちょっとまってほしい
• そもそも、「データベースを使うと遅い」の
であれば、データベースって業務に使えない
です…
• 「データベースを使うテストは遅い」は都市
伝説?
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
実例(その1)
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
実例(その2)
https://twitter.com/setoazusa/status/194746629159526400
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
• Java開発の場合は、スローテストの原因になる
のは、コンテナの立ち上げ
• ユニットテストの望ましい姿(独立性)からは外れ
ますが、Spring Frameworkの
SpringJUnit4ClassRunnnerはContainerの
Contextをキャッシュする実装になっているので、
初期化コストはおさえられる。
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
何がデータベースを使うテストを難しくするのか
• ネックとなるのはテストの実行時間よりも、
テストデータのメンテナンスに必要なコスト
が失わせる、テストのリズム感
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
Excelを捨てよ、街へ出よう
• IDEで作業しているときに一々Excelたちあげ
るのたるいし…
• Excelでファイルを開いているためにIDEがビ
ルドエラーになるのってあるあるですよね?
• そもそも分散バージョン管理しているとマー
ジできない!
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
XMLだけど自動生成すれば問題ないよねっ
• 本当はYAMLなりJSONにしたかったのですが、
DBUnitとの相性との関係で。
• テストデータ作成時は開発者のテストデータに
一度投入した後、mavenプラグインでエクス
ポートする方法を採用
• ただ、mavenでエクスポートするのはあまり使われ
てないみたい..
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
データベースのアサーション、どうやろう…
• データベースの更新系処理は、データベースの
テーブル全体をアサーションするのがセオリー。
• しかし、テストに関係してない、更新されない
データまで期待値に含む必要があるため、テス
トデータのメンテナンスコストが増大する問題
がある。
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
• データベースの更新・削除の前後で、テーブ
ルの状態の差分を取り、その差分をアサー
ションするようにDBUnitをカスタマイズ。
(デルタアサーション)
• このことのより、期待値のデータのメンテナ
ンスコストを削減
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
データベースマイグレーションはTDDに必須
• 開発者の相互の環境がテスト実行に影響を与
えないようにするため、開発者ごとに
Vagrant でデータベースを用意。
• ローカル/CI/開発環境/ステージング/本番の
スキーマ構成を管理するため、データベース
マイグレーションツールを使用。
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
MyBatis Migrationsによるマイグレーション
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
Controller層のテストあるある
Controller層はユニットテスト書けなくはない
けど、ブラウザから叩く時の条件とは違うし、
struts-config.xmlが正しいかは結局Tomcat起
動しないとわからないし…
だったらユニットテストいらないじゃん!
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
Controller層のテスト
• End to Endになるべく近い条件でテストした
い
• Spring MVC Test Frameworkはhttpのリク
エストを高い精度でシミュレートできるため、
これでControllerをテスト
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
Spring によるRESTful APIのテスト
mockMvc.perform(get("/company/fieldnotes.jp/users/[email protected]"))
.andExpect(jsonPath("$.id",is("[email protected]")))
.andExpect(jsonPath("$.firstName",is("Hiroyuki")))
.andExpect(jsonPath("$.lastName",is("Ohnaka")))
.andExpect(status().isOk());
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
モックした場合のコンテナー汚染問題
• Dependency Injectionしたコンポーネント内の
オブジェクトをモックした場合、Springのコン
テナー内のオブジェクトが汚染される問題
• モックを使うテストケースに@DirtyContextを
つければ回避できるが、テストが目に見えて遅
くなるため @After のメソッドの中でオブジェ
クトを差し戻すように修正
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
フロントエンドのユニットテスト
• サーバーサイドのみのテストでもフロントエ
ンドに良い効果は及ぼせる
• フロントエンドを改修する時に、サーバーサ
イドをテストでガードできているため、リグ
レッションの検証範囲を限定できる。
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
とはいうものの…
• 開発が進むにつれ、フロントエンドにテスト
がないことよりサーバーサイドとのリズムの
ずれが顕在化
• 結合する時のテストの粒度のずれ
• リファクタリングのしやすさのずれ
• ブランチのマージする時のリスクのずれ
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
「安西先生、テストが書きたいです…」
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
フロントエンドのテストへの取り組み
• mocha でモデルのバリデーションのテスト
から、そこから徐々に拡大
• CasperJs + mocha でRestfulのAPIをモッ
クした状態での機能テスト
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
• もともとGruntでビルドするようにしていた
ため、テスティングフレームワークの組み込
み自体は意外にすんなりいった
• ただ、テストの書き方は現在も試行錯誤中
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
end to end のシステムテスト
• リグレッションテストは、イテレーション(1
週間ないし2週間)の最後に、開発メンバー全
員で手動で行うことによって実施
• テストケースはTestLinkで管理
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
end to end レベルのシステムテスト
• プロジェクト終盤から、Geb+Spockによる
自動リグレッションテストに徐々に移行
• 現在は、自動リグレッションテストと手動リ
グレッションテストが共存している状態
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
デプロイ自動化の問題
• プロジェクトのミッションとしてDevOpsの
推進があり、その一環として自動デプロイを
実施
• 自動デプロイの実装時に、スクリプトの問題
による不具合・リグレッションが多発
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
ServerSpecによるデプロイ作業の検証
ServerSpecでデプロイスクリプトの動作を検証
し、CIサーバーから各環境に対してテストを実
施することで事態を改善
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
describe service('jboss') do
it { should be_enabled }
it { should be_running }
end
describe command("wget -O - http://localhost:8080/service/status") do
it { should return_exit_status 0 }
end
describe "setting.propetiesがデプロイされていること" do
describe command("diff #{RESOURCES}/setting.properties
#{JBOSS_HOME}/properties/setting.properties") do
it { should return_exit_status 0 }
end
end
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
• サーバー環境に対する操作等の正当性をテス
ティングフレームワークで担保するのは、リ
ターンを得やすいためおすすめ
• 他にも、環境ごとのプロパティファイルの項
目に不整合がないかの検証をCI環境で実施す
るなど(RSpecを使用)
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
アジェンダ
• なぜTDDするのか
• どうTDDするか
• 技術的な各論
• なぜTDDするのか(again)
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
荒みきったコード
疲弊しきった現場
爆弾処理のようなリリース
http://www.flickr.com/photos/okinawa-soba/2951808529/http://www.flickr.com/photos/22719239@N04/2246462044/http://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB:Bomb_neutralizing_EOD_9.jpg
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
もうウンザリです。何も改善できません。
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
もうウンザリです。何も改善できません。
「しかし、私たちにはプログラミングをする本当の理由
があるはずです。」
「もし、自分や同僚がプログラミングを楽しめるなら、
どんなシステムに取り組んでいるかは重要ではありませ
ん。そのシステムに対してきちんとした仕事ができるは
ずで、そうでなければ待っているのは落胆です。そう
なってしまっては何の楽しみもありませんし、私たちは
そんな目に遭うべきではありません。」
「レガシーコード改善ガイド」
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
「君が質の高いソフトウェアを届けることは誰
にも止められない。君が現場に立って、お客さ
んに向けてプロジェクトの状況と、プロジェク
トに必要なことを誠実に伝えることも誰にも止
められないんだ。」
「アジャイルサムライ」
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
なぜTDDするのか
私の場合…
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
「君にも君を動かしているものがあるでしょう?」
あなたの場合…
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
「世界よ 変われ」(※)
• ミッションを共有する仲間が集うコミュニ
ティで、
• プログラマーが一人一人知恵を持ち寄り、議
論し、勇気づける場が出来たときに、世界は
変わる
• そう思う。※いきものがかり 「NEW WORLD MUSIC」
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
あなたがコミュニティです
• キミのいる世界、わたしのいる世界
• 自分が完璧なエンジニアでないことを認める
• 問題を他人事にしない。真摯に向き合う
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
「信頼で結ばれた共同体」のために
• スキルの有無/キャリアの長短を人を計る尺度に
しない
「新人だから知らないと思うけど」なんてとんでもない!
• IT技術者としてのバックグラウンドを尊重する
• ペアの意志決定を尊重する
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
この発表での結論
• TDDを導入するのに必要なのは、チームをつ
くること。
• チームをつくるということは、コミュニティ
をつくるということ。
• そのことに、ウォータフォールもアジャイル
も関係ないと思います。
#ccc_r11
Copyright 2014 Hiroyuki Ohnaka
#ccc_r11
最後に
• 自分たちのやっていることがTDDのプラクティ
スに沿っているかどうか、そのことはあまり気
にしていないです。
• 答えは、みなさんの現場にあります。
• Have a nice Testing!
• ご静聴ありがとうございました。