Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

開発を効率的に進めるられるまでの道程

25,243 views

Published on

DroidKaigi 2015の講演資料です。

Published in: Technology
  • Be the first to comment

開発を効率的に進めるられるまでの道程

  1. 1. DroidKaigi 2015/04/25 @cattaka_net 開発を効率的に 進めるられるまでの道程 Takao Sumitomo @cattaka_net
  2. 2. DroidKaigi 2015/04/25 @cattaka_net 自己紹介 ● 住友 孝郎(Takao Sumitomo) ● Androidアプリ開発者 ● 開発経歴 ● Androidアプリ ● iOSアプリ(ちょっとだけ) ● 業務系Webアプリケーション ● 業務系Windowsアプリ ● その他 ● 電子工作 ● OpenCV ● ウォンテッドリー株式会社所属 2014年12月〜
  3. 3. DroidKaigi 2015/04/25 @cattaka_net Androidアプリ開発の経歴 ● HT-03Aの頃(2009年くらい)からAndroidアプリ 作ってます。 ● 当時は受託と派遣を主にやってました。 ● 手に負えなくなったアプリの改修をよくやってました
  4. 4. DroidKaigi 2015/04/25 @cattaka_net プロの力が身につく Androidプログラミングの教科書
  5. 5. DroidKaigi 2015/04/25 @cattaka_net 駄目コードについて、C87で書きました 技術サークル TechBooster
  6. 6. DroidKaigi 2015/04/25 @cattaka_net トピック ● アプリ開発の効率化について ● テストを書くに至った経緯 ● 開発途中からテストを導入する話
  7. 7. DroidKaigi 2015/04/25 @cattaka_net アプリ開発の効率化について
  8. 8. DroidKaigi 2015/04/25 @cattaka_net ボトルネックの潜む場所 ● 開発で行うこと ● プログラムを書く ● ソースコード管理 ● テスト ● テスト版アプリの配布 ● これらをどこまで自動化するか?
  9. 9. DroidKaigi 2015/04/25 @cattaka_net ボトルネックの対策 ● 開発で行うこと ● プログラムを書く – 諦めて書く。良いライブラリを使う。良いIDEを使う。 ● ソースコード管理 – GitやSVNを使う。Git FlowやGitHub Flowを使う。 ● テスト – JUnitを使う。 – JenkinsやTravisCIやCircleCIで自動化する。 ● テスト版アプリの配布 – DeployGate等を使う。 ここが一番ネックになる
  10. 10. DroidKaigi 2015/04/25 @cattaka_net なのでテストの話をします
  11. 11. DroidKaigi 2015/04/25 @cattaka_net テストを書くに至った経緯
  12. 12. DroidKaigi 2015/04/25 @cattaka_net 開発してるとよくある話 ● 「バグゼロで」 ● 「品質は100%で」
  13. 13. DroidKaigi 2015/04/25 @cattaka_net どうしてたか? ● エクセルのテストシート(山盛り) ● エビデンス(という名のスクリーンショット)を取る ● 全機種で実機テスト ● 仕様変更があったとき →全部再テストしてくださいね^^ ツライ!(゚Д゚)ツライ!(゚Д゚)
  14. 14. DroidKaigi 2015/04/25 @cattaka_net よくある問題 ● 小さなリファクタリング ● 意識してないところで壊れる、、orz ● リファクタリングしないようにする ● ハウルの動く城みたいになる ● 書きたいように書けなくなるので更にストレスが貯まる ツライ!(゚Д゚)
  15. 15. DroidKaigi 2015/04/25 @cattaka_net テストを書き始める ● 最初はロジックのテストから書く ● 要件一覧表の1項目1テストを書くこともやった ● 実は個人的に一番効果があった(効率悪いけど) ● 「壊す恐怖」から解放された ● 以降、設計レベルからテストを書くようにした
  16. 16. DroidKaigi 2015/04/25 @cattaka_net 開発途中からテストを導入する話
  17. 17. DroidKaigi 2015/04/25 @cattaka_net 普通のテスト 要求分析 基本設計 機能設計 詳細設計 コーディング 受け入れテスト システムテスト 結合テスト 単体テスト
  18. 18. DroidKaigi 2015/04/25 @cattaka_net 普通のテスト 要求分析 基本設計 機能設計 詳細設計 コーディング 受け入れテスト システムテスト 結合テスト 単体テスト 通常はテストも順番に作る。 後から作るのは大変。
  19. 19. DroidKaigi 2015/04/25 @cattaka_net アプローチ ● 外部依存する箇所にDI(オレオレ可)を入れる ● 通信処理 ● データベース ● プリファレンス ● グローバル変数を取る(static変数) ● シングルトンという名のグローバル変数も取る ● 投げっぱなしのスレッドを止める ● 最小限のリファクタリング ● ひたすらテストを書く
  20. 20. DroidKaigi 2015/04/25 @cattaka_net ひたすらテストを書く
  21. 21. DroidKaigi 2015/04/25 @cattaka_net 具体的な修正1 ● 修正前 アプリケーション 通信処理データベース SharedPreferences
  22. 22. DroidKaigi 2015/04/25 @cattaka_net 具体的な修正2 ● 修正後 アプリケーション 通信処理データベース SharedPreferences
  23. 23. DroidKaigi 2015/04/25 @cattaka_net 具体的な修正3 ● テスト時の構成 アプリケーション 通信処理のモックデータベースのモック SharedPreferencesのモック
  24. 24. DroidKaigi 2015/04/25 @cattaka_net 具体的な修正3 ● テスト時の構成 アプリケーション 通信処理のモックデータベースのモック SharedPreferencesのモック 要はこれらをモックに 差し替えられれば テストが書ける
  25. 25. DroidKaigi 2015/04/25 @cattaka_net どうやって差し替えるか ● DaggerなどのDIライブラリを使う ● オレオレDIを使う オレオレDIでも無いより良い
  26. 26. DroidKaigi 2015/04/25 @cattaka_net SharedPreferencesの差し替え ● Context#getSharedPreferencesを付ける ● 呼ぶときの引数にPrefix等を付ける ● 直接↑を呼ぶのではなく、Factoryクラスを作る
  27. 27. DroidKaigi 2015/04/25 @cattaka_net SharedPreferencesの差し替え プロダクションコード public class SharedPreferencesFactory { static SharedPreferencesFactory INSTANCE = new SharedPreferencesFactory(); public static SharedPreferencesFactory getInstance() { return INSTANCE; } public SharedPreferences newInstance(Context context, String name) { return context.getSharedPreferences(name, Context.MODE_PRIVATE); } } テスト用のダミー public class DummySharedPreferencesFactory extends SharedPreferencesFactory { public SharedPreferences newInstance(Context context, String name) { SharedPreferences pref = context.getSharedPreferences( "test_" + name, Context.MODE_PRIVATE); pref.clear(); return pref; } } テストのときは ここをダミーに差し替える
  28. 28. DroidKaigi 2015/04/25 @cattaka_net SQLiteOpenHelperの差し替え ● RenamingDelegatingContextを使えば 一時的に別のDBファイルにできる ● SQLiteOpenHelperにname=nullを渡すと オンメモリのデータベースが作れる どっちでもテストは書ける
  29. 29. DroidKaigi 2015/04/25 @cattaka_net SqlteOpenHelperの差し替え プロダクションコード public class OpenHelperFactory { static OpenHelperFactory INSTANCE = new OpenHelperFactory(); public static OpenHelperFactory getInstance() { return INSTANCE; } @Override public OpenHelper createOpenHelper(Context context) { return new OpenHelper(context); } } テスト用のダミー public class DummyOpenHelperFactory extends OpenHelperFactory { public OpenHelper createOpenHelper(Context context) { Context c = new RenamingDelegatingContext(context, "test_"); return new OpenHelper(c); } } テストのときは ここをダミーに差し替える
  30. 30. DroidKaigi 2015/04/25 @cattaka_net 通信処理の差し替え ● 予め通信処理は1つにまとめておく ● オレオレDIで通信処理を差し替える ● 偽の通信データを返すようにする ● 偽の通信データは androidTest下のassetsに入れる
  31. 31. DroidKaigi 2015/04/25 @cattaka_net ひたすらテストを書く ● ブラックボックステスト ● ウォークスルー ● コンバージョンに繋がるところは重点的に書く ● ログイン周り ● 応募 ● ユーザーのプロフィール入力 ● テストの粒度はマチマチ
  32. 32. DroidKaigi 2015/04/25 @cattaka_net ひたすらテストを書く
  33. 33. DroidKaigi 2015/04/25 @cattaka_net 悲しいこともあるけど、、
  34. 34. DroidKaigi 2015/04/25 @cattaka_net 具体的な例
  35. 35. DroidKaigi 2015/04/25 @cattaka_net たとえばリスト画面 ● この画面に関連する部品 ● Activity ● Adapter ● ListView ● Database ● どのテストを書く? Activity ListView Database Adapter
  36. 36. DroidKaigi 2015/04/25 @cattaka_net Adapterのテスト ● Adapter単独で考える ● Contextとダミーのデータを与える ● getViewで生成されたViewを確認する ● InstrumentationTestCaseが使える Activity ListView Database Adapter Context Adapter DummyData 生成されたView getViewメソッド これらが対応しているかのテストを書く テストのときは切り離して考える
  37. 37. DroidKaigi 2015/04/25 @cattaka_net Adapterのテスト public void testGetView() { List<CheckListItem> dummys = new ArrayList<>(); { // ダミーデータを作る dummys.add(new CheckListItem(1L, 1L, 1L, "Label1")); dummys.add(new CheckListItem(2L, 2L, 2L, "Label2")); } Context context = getInstrumentation().getTargetContext(); MyAdapter sup = new MyAdapter(context, dummys); { // 1つめのViewの表示内容を確認する View view = sup.getView(0, null, null); assertThat(view, is(Matchers.instanceOf(CheckedTextView.class))); assertThat(((CheckedTextView)view).getText().toString(), is("Label1")); } { // 2つめのViewの表示内容を確認する View view = sup.getView(1, null, null); assertThat(view, is(Matchers.instanceOf(CheckedTextView.class))); assertThat(((CheckedTextView)view).getText().toString(), is("Label2")); } }
  38. 38. DroidKaigi 2015/04/25 @cattaka_net Databaseのテスト ● CRUD系はテストを書く ● RenamingDelegateContextが便利 ● InstrumentationTestCaseが使える Activity ListView Database Adapter テストのときは切り離して考える Database DummyData1 DummyData2 insert select これらが対応しているかのテストを書く
  39. 39. DroidKaigi 2015/04/25 @cattaka_net Databaseのテスト @Override protected void setUp() throws Exception { super.setUp(); Context context = new RenamingDelegatingContext( getInstrumentation().getTargetContext(), "test_"); mOpenHelper = new OpenHelper(context); } public void testInsertSelect() { CheckListEntry orig = new CheckListEntry(); orig.setTitle("hoge"); { // INSERTする mOpenHelper.registerEntry(orig); } CheckListEntry dest; { // SELECTする Long id = orig.getId(); dest = mOpenHelper.findEntry(id, false); } { // 確認する assertThat(dest.getTitle(), is("hoge")); } }
  40. 40. DroidKaigi 2015/04/25 @cattaka_net Activity ● 外部依存やストレージのみダミーに置き換える ● ActivityInstrumentationTestCase2が使える ● それぞれの部品の疎通確認程度に留める Activity ListView Database Adapter Activity ListView DummyDatabase Adapter Databaseのみダミーに置き換えて考える これらが対応しているかのテストを書く
  41. 41. DroidKaigi 2015/04/25 @cattaka_net ツールやライブラリ ● 基本的に一般的なものを使用 ● JUnit4 ● ./gradlew connectedAndroidTest ● ./gradlew createCoverageReport ● Espresso (android-test-kit) ● UI周りのテストが簡潔に書ける ● Mockito ● モックが簡単に作れる ● Crashlytics ./gradlew create(Debug/Release)CoverageReport
  42. 42. DroidKaigi 2015/04/25 @cattaka_net connectedAndroidTestのレポート
  43. 43. DroidKaigi 2015/04/25 @cattaka_net createCoverageReportのレポート
  44. 44. DroidKaigi 2015/04/25 @cattaka_net 標準でも十分強力
  45. 45. DroidKaigi 2015/04/25 @cattaka_net まとめ
  46. 46. DroidKaigi 2015/04/25 @cattaka_net いきなり効率化は無理
  47. 47. DroidKaigi 2015/04/25 @cattaka_net 少しずつ自動化しよう
  48. 48. DroidKaigi 2015/04/25 @cattaka_net まずはテストを書くところから始めよう
  49. 49. DroidKaigi 2015/04/25 @cattaka_net ボトルネックの対策 ● 開発で行うこと ● プログラムを書く – 諦めて書く ● ソースコード管理 – GitやSVNを使う。GitFlowやGitHubFlowを使う。 ● テスト – JUnitを使う – JenkinsやTravisCIやCircleCIを使う ● テスト版アプリの配布 – DeployGateやFabricを使う ここが解決すれば 後の自動化もできる
  50. 50. DroidKaigi 2015/04/25 @cattaka_net サンプルアプリ ● FastCheckList ● テストが直ぐに実行できるようになっています
  51. 51. DroidKaigi 2015/04/25 @cattaka_net 貴方がテストを書けば 効率は上げられる
  52. 52. DroidKaigi 2015/04/25 @cattaka_net ご清聴ありがとうございました Takao Sumitomo @cattaka_net

×