Javaアプリケーション開発におけるユニットテストとTDDの実践 Java Day Tokyo 2014

3,934 views

Published on

Published in: Technology
0 Comments
15 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,934
On SlideShare
0
From Embeds
0
Number of Embeds
165
Actions
Shares
0
Downloads
24
Comments
0
Likes
15
Embeds 0
No embeds

No notes for slide

Javaアプリケーション開発におけるユニットテストとTDDの実践 Java Day Tokyo 2014

  1. 1. Javaアプリケーション 開発における テストとTDDの実践 Shuji Watanabe (@shuji_w6e) 1
  2. 2. 自己紹介
  3. 3. 渡辺 修司 / @shuji_w6e JUnit実践入門(技術評論社) クラスメソッド株式会社 札幌にて在宅勤務 AWS関連 ポータルサイト構築 Spring, Ember.js, d3-data 4刷!
 累計1万部
  4. 4. クラスメソッド札幌オフィス開設! AWSエンジニア / iOSエンジニア U/Iターン歓迎! 7月初旬 開設予定! アプリ屋から 移籍可能
  5. 5. Javaアプリケーション 開発における テストとTDDの実践 Shuji Watanabe (@shuji_w6e) 5
  6. 6. Javaアプリケーション 開発における テストとTDDの実践 Shuji Watanabe (@shuji_w6e) 6
  7. 7. Long live testing ?
  8. 8. http://www.flickr.com/photos/peakman2/1017866785/ _人人人人人人人人人_   > レガシーコード <    ̄Y^Y^Y^Y^Y^Y^Y^Y ̄
  9. 9. http://www.flickr.com/photos/bsom/4625185702/ 貴様のプロジェクトでは、 効果的なテストをしてるか?
  10. 10. 自動化テストの成熟度 0 自動化されたテストを行っていない、標準出力 1 効果的とは言えないが、一部のテストを自動化している 2 主要な部分のテストは自動化され、継続的インテグレーショ ンなどの「自動化」をはじめている 3 プロジェクト計画やアーキテクチャが自動化されたテス トを前提としている 4 テストをはじめとした「自動化」が開発プロセスに組み込ま れている 5 自動化が開発プロセスに組み込まれ、プロジェクトやチーム に合わせて改善を続けている
  11. 11. ユニットテストは基本スキル 最初から出来る人はいません たくさん書けばそれだけ覚えます TDDBC, JJUG CCCなど勉強会にでましょう 社内でテスト勉強会をやりましょう JUnit実践入門がオススメです!
  12. 12. http://www.flickr.com/photos/palermobootcamp/5464512672/ TDD!TDD! テスト!テスト!
  13. 13. 継続的インテグレーション
 と
 ユニットテスト
  14. 14. 手作業したら負け
  15. 15. 継続的インテグレーション バージョン管理システムと連動 コミット毎にテストなどを自動実行 テスト失敗時に通知(メールなど) 簡単に導入可能 Jenkinsがスタンダード
  16. 16. 自動化された開発環境の例
  17. 17. 自動化のメリット 手作業によるコストの削減 手作業によるミスの削減 コンピューティングリソースを有効活用 文句を言わずに繰り返し何度でも実行 楽しいw
  18. 18. http://www.flickr.com/photos/jas_132/5403388208 ユニットテストは 最高のパートナー
  19. 19. ユニットテストの特徴 自動的に実行可能なプログラム 実行コスト < 実装コスト / 手動テスト 変更の影響がなければ常に成功を維持 早い段階から繰り返し実行することで 効果が最大となる
  20. 20. テストの実装時期とテスト回数 コード量/開発の進 テスト数 テスト 回数 A B C テスト 回数 テスト 回数
  21. 21. 変更毎にテストを実行 ソースコードの修正の影響 可能な限り早く影響を検知 リグレッション(デグレーション)対策 防止する ○ 即座に修正できるようにする
  22. 22. Amazon EC2の活用 Elasticなコンピューティングリソース 調達が容易 必要に応じて起動すればコストも削減 VPN接続も可能 簡単構築、簡単インストール
  23. 23. データベースを操作する メソッドのテスト
  24. 24. DAO, Repository, EntityManager モデルの永続化を行うレイヤー RDBとの通信部分を分離する Hibernate, S2Dao などのフレームワーク
  25. 25. 永続化層のユニットテスト戦略 外部システムに依存する部分はモック派 外部システムに依存すべきでない 実行に時間がかかるのはよくない RDBは実質的にシステム内部とみなす派 SQLやクエリ実行まで含めて実装 時間がかかってもテストしたい
  26. 26. 4 Phase Test 初期化 ー Setup テスト実行時の状態を一定にする 実行 ー Exercise テスト実行後の影響を観測する 検証 ー Verify 期待する結果となるかを検証する 後処理 ー Teardown 次のテストへの影響させない
  27. 27. 初期化 ー Setup DBデータの初期化 関連テーブルの削除 シーケンス システム時間 初期化にかかる処理時間 テスト用データの準備 すべて自前で行うのは かなり大変....
  28. 28. 実行 ー Exercise テスト対象オブジェクト(Daoなど)の準備 フレームワークのは単体で実行できるか? コネクションプールやデータソース トランザクション境界 1つのメソッド(SQL)毎にテストを実行 DBの状態によって結果も変わる
  29. 29. 検証 ー Verify モデルの検証 Assertion / Hamcrest Matcher API シーケンス番号、システム時間などの除外 順番に注意(order by) DBデータへの反映の検証 Create, Update, Deleteでは必須
  30. 30. 後処理 ー Teardown 1つのテストで複数のことを検証しない 次のテストの初期化に任せて何もしない テスト失敗時、DBの状態が残る
  31. 31. テスト方針 リアルDBを利用 フィクスチャはYAMLフォーマットで定義 初期化処理でDBをセットアップ 後処理ではDBを操作しない JUnit, DbUnit, cmtest-db を利用
  32. 32. DbUnit JUnitの拡張フレームワーク JUnit 3系 データベースの初期化と後処理 フィクスチャ(データ) 検証 http://dbunit.sourceforge.net/
  33. 33. public class SampleTest extends DBTestCase { protected void setUp() throws Exception { super.setUp(); DatabaseOperation.CLEAN_INSERT
 .execute(connection, dataSet); } public void testMe() throws Exception { IDataSet databaseDataSet = getConnection().createDataSet(); ITable actualTable = databaseDataSet.getTable("TABLE_NAME"); IDataSet expectedDataSet = new FlatXmlDataSetBuilder() .build(new File("expectedDataSet.xml")); ITable expectedTable = 
 expectedDataSet.getTable("TABLE_NAME"); Assertion.assertEquals(expectedTable, actualTable); } }
  34. 34. cmtest-db DbUnitのラッパーライブラリ JUnit4対応 YAMLによるフィクスチャ アノテーションによるテストの定義 JUnit4系のモダンなテストコードを実現 https://github.com/classmethod/cmtest/tree/master/cmtest-db
  35. 35. public class UserRepositoryTest { @Rule public DbUnitTester tester = DbUnitTester .forJdbc("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/cmtest") .username("root").password("").create(); @Fixture(resources = "2-users.yaml") @Test public void updateによる更新() throws Exception {
 IDataSet expected = YamlDataSet
 .load(getClass().getResourceAsStream("yaml")); sut.update(user); tester.verifyTable("users", expected); } }
  36. 36. その他のポイント フィクスチャ重要 0件の場合、1件の場合、2件の場合 Enclosedテストランナーを活用 ローカル実行 スローテスト システム時間など難しい部分は無視も一手

×