Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

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

25 820 vues

Publié le

DroidKaigi 2015の講演資料です。

Publié dans : Technologie
  • Soyez le premier à commenter

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

  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

×