マルチモジュールなプロジェクトでテストはどう変わるか? / How change testing in modular architecture
by
tkmnzm
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
マルチモジュールな プロジェクトで テストはどう変わるか? Nozomi Takuma 2019/2/7 DroidKaigi2019
Slide 2
Slide 2 text
自己紹介 Nozomi Takuma SWET@DeNA所属 (2018/3~) Androidとテストが好き
Slide 3
Slide 3 text
はじめに
Slide 4
Slide 4 text
マルチモジュールって? :app :featureA :featureB アプリの実装を 複数のモジュールに 分割する
Slide 5
Slide 5 text
:app featueA package featureB package これまでのアーキテクチャ appモジュール内に 実装をまとめた モノリシックな構成
Slide 6
Slide 6 text
:app :featureA :featureB :app featueA package featureB package
Slide 7
Slide 7 text
app/build.gradle
Slide 8
Slide 8 text
なぜマルチモジュールにするのか? ● 差分ビルドによるビルド時間短縮のため ● App BundleやInstant App対応のため ● それぞれの機能を分離させることで機能 間の独立性を保つため
Slide 9
Slide 9 text
マルチモジュールプロジェクトの テストで変わらないこと ● テストを書くこと ● テストの書きかた
Slide 10
Slide 10 text
マルチモジュールプロジェクトの テストで変わる3つのポイント 1. DI 2. テスト方針 3. メトリクス収集
Slide 11
Slide 11 text
DI
Slide 12
Slide 12 text
DI(Dependency Injection)って? ● コンポーネントの依存を外から渡せる ようにする ● テストをしやすくするためのパターン として利用される ● DI LibraryとしてDaggerが有名
Slide 13
Slide 13 text
マルチモジュールでのDI悩みポイント 1. モジュール間の依存関係を クリーンに保ちたい 2. 依存の定義をモジュール内で完結 させたい
Slide 14
Slide 14 text
モジュール間の依存をクリーンに保ちたい app module feature module 依存解決にapp module内のクラスが 必要な場合、循環参照が発生する可能性がある
Slide 15
Slide 15 text
Daggerで困る例
Slide 16
Slide 16 text
Daggerで困る例 feature module内の Activity app module内の Application
Slide 17
Slide 17 text
依存の定義をモジュール内で完結させたい ● どのように依存が解決されるかの定義は モジュール内で完結できるとうれしい ● DaggerでいうとModuleクラスの定義 など
Slide 18
Slide 18 text
マルチモジュールでのDI DIのやりかたやDIライブラリの使い方に よっては、前述の悩みポイントに対応する ため書き方や構成の変更が必要になる
Slide 19
Slide 19 text
話しきれないので... 『マルチモジュールプロジェクトでの Dagger2を用いたDependency Injection』 02/07 11:20 - 11:50@Hall A
Slide 20
Slide 20 text
サンプル ● Dagger-Android https://github.com/tkmnzm/MultiModulePlayground
Slide 21
Slide 21 text
テスト方針
Slide 22
Slide 22 text
モジュール化によって得られるメリット ● ビルド時間短縮による開発速度向上 ● 意味のあるまとまりに分けることによって 他モジュールへの影響範囲が小さくなる
Slide 23
Slide 23 text
動作確認もモジュール内で完結 できるようにしたらどうだろう? モジュール化のメリットを得るために
Slide 24
Slide 24 text
モジュール内で動作確認を完結できると ● 各モジュールの動作確認をするために 全体のapkをビルドしなくてよい ● 動作確認済みのモジュールを使用する ことで、モジュールを結合したときの 動作確認が楽になる
Slide 25
Slide 25 text
モジュール内でどんな動作確認が できていたら嬉しいか? テスト方針を考える問いかけ
Slide 26
Slide 26 text
とあるモノリシックなプロジェクトの例 Presenter UseCase Repository 呼び出していることを 意味する矢印
Slide 27
Slide 27 text
とあるモノリシックなプロジェクトの例 Presenter UseCase Repository ユニット テスト
Slide 28
Slide 28 text
● レイヤー内の代表的なクラスのユニット テストは充実していた(UseCase,Repo など) ● しかし上記以外の実装もたくさんあり テストが手薄なところもあった とあるモノリシックなプロジェクトの例
Slide 29
Slide 29 text
● このモジュールの動作確認はいまある テストだけだと足りない気がする... ● この例の場合、UI部分やITテストが 不足していた モジュールとして分割してみた時
Slide 30
Slide 30 text
● まとまりの責務を考えるきっかけ ● モノリシックなプロジェクトではレイ ヤーごとにどうテストするかを考える ことが多かったが、モジュール毎とい う新しい視点が生まれる モジュールとして切り出す
Slide 31
Slide 31 text
● モジュール内のテスト ● モジュールをまたいだテスト モジュールのテスト方針を考えてみよう
Slide 32
Slide 32 text
モジュール内のテスト
Slide 33
Slide 33 text
モジュールの設計時に考えたいこと ● モジュールの責務 ● モジュールのテスト範囲
Slide 34
Slide 34 text
自動テストの手段はいろいろ ITテスト ユニット テスト UIテスト
Slide 35
Slide 35 text
例えばこんなモジュール① Utility Utility Utility
Slide 36
Slide 36 text
例えばこんなモジュール① Utility Utility Utility ユニット テスト
Slide 37
Slide 37 text
例えばこんなモジュール② Logic Logic Android PF
Slide 38
Slide 38 text
Logic Logic Android PF 例えばこんなモジュール② ユニット テスト IT テスト
Slide 39
Slide 39 text
Logic Logic Android PF 例えばこんなモジュール② IT テスト
Slide 40
Slide 40 text
例えばこんなモジュール③ Activity Logic Android PF
Slide 41
Slide 41 text
Activity Logic Android PF 例えばこんなモジュール③ UI テスト IT テスト
Slide 42
Slide 42 text
Activity Logic Android PF UI テスト 例えばこんなモジュール③
Slide 43
Slide 43 text
方針考えたけど何から手を付ける? ユニットテストで十分なところは ユニットテストからはじめる ユニット テスト
Slide 44
Slide 44 text
導入の容易さ ITテスト ユニット テスト UIテスト
Slide 45
Slide 45 text
FBサイクルの速さ ITテスト ユニット テスト UIテスト
Slide 46
Slide 46 text
ITテスト・UIテスト ユニットテストでは動作確認として 不足している部分に追加していく しかし、自分自身はAndroid PFが絡むテ ストは避けがちだった
Slide 47
Slide 47 text
ITテスト・UIテスト ユニットテストでは動作確認として 不足している部分に追加していく しかし、自分自身はAndroid PFが絡むテ ストは避けがちだった AndroidのAPIが絡むテストも導入しやすくなるよう 環境が変わりつつある
Slide 48
Slide 48 text
Project Nitrogen 実行環境の差分を統一した ● API ● Test Runner
Slide 49
Slide 49 text
API Robolectric上でも実機上でも実行可能
Slide 50
Slide 50 text
Test Runner
Slide 51
Slide 51 text
Project Nitrogenに期待すること ● ローカルでのテスト: Robolectric上で素早く実行 ● CIでのテスト: 実機やVirtual Device上など fidelity(忠実度)の高い環境で実行
Slide 52
Slide 52 text
No content
Slide 53
Slide 53 text
現状は... ● Robolectricで実行するには: src/testにテストコードを配置 ● Deviceで実行するには: src/androidTestにテストコードを配置
Slide 54
Slide 54 text
ワークアラウンド
Slide 55
Slide 55 text
モジュール内のテストまとめ ● モジュールの責務とテスト範囲を考える ● まずはユニットテストからはじめる ● ITテストやUIテストはつまづきがち だが、導入しやすい環境が整いつつある
Slide 56
Slide 56 text
もしテストを書く時間がなくても ● テスタビリティは意識して実装したい ● いざテストを書こうとしたときにテスト が書きにくい状態になっていると まずはリファクタリングが必要になる
Slide 57
Slide 57 text
モジュールをまたいだテスト
Slide 58
Slide 58 text
テストの方針 Module B Module A Module A Module B モジュールごとにテスト 結合してテスト
Slide 59
Slide 59 text
モジュールごとにテスト FeatureBをモック化
Slide 60
Slide 60 text
結合してテスト 実インスタンスや Spyを使用
Slide 61
Slide 61 text
モジュールをまたぐといっても ● テストの書き方はいままでと変わらない ● 他モジュールへの依存を外から渡すように していれば、これまでどおりテストダブル が使用できる
Slide 62
Slide 62 text
どれを選択する? ● ケース・バイ・ケース ● 自分のプロダクトではどんな不具合が起き やすいか?(単体でも拾える?結合しない とだめ?)というのは判断に使えそう
Slide 63
Slide 63 text
テストメトリクス収集
Slide 64
Slide 64 text
テストメトリクス Android開発でよく 使われているのは ● JUnit実行結果 ● Jacoco
Slide 65
Slide 65 text
マルチモジュールでのテストメトリクス収集 各モジュールのレポートをまとめて 見たい場合、結果のマージが必要
Slide 66
Slide 66 text
Jacocoについては... 『Spek2+MockK+JaCoCoでイケてるUnit Test環境を手に入れろ!』 02/08 11:20-11:50@Room 1
Slide 67
Slide 67 text
PIT Java、その他JVM言語用MutationTesting ツール http://pitest.org/
Slide 68
Slide 68 text
Mutation Testing ● プロダクトコードを機械的に変更し、 変更されたコードに対してテストを実行 ● テストが失敗するかを確認することで、 テストコードが振る舞いの変更を検知 できるかチェックする
Slide 69
Slide 69 text
例: Conditionals Boundary Mutator if (hoge <= 5) { // do something } if (hoge < 5) { // do something } hogeが5のときの 振る舞いが Mutatorによって変更
Slide 70
Slide 70 text
例: Conditionals Boundary Mutator if (hoge <= 5) { // do something } if (hoge < 5) { // do something } hogeが5のときの 振る舞いが Mutatorによって変更 hogeが5のときの テストが正しく書かれて いれば失敗するはず...
Slide 71
Slide 71 text
例: Conditionals Boundary Mutator テストを実行し... ● テストが失敗する: OK ● テストが成功する: NG 境界値チェックなど、不足しているテストケースを 見つける手助けをしてくれる
Slide 72
Slide 72 text
PITのレポート
Slide 73
Slide 73 text
PITのレポート
Slide 74
Slide 74 text
PITのうれしいところ ● Mutation Coverageと Line Coverageが見られる ● Android用GradlePluginがある ● Kotlinのサポートが進んでいる
Slide 75
Slide 75 text
実行結果のマージ: マージ処理抜粋
Slide 76
Slide 76 text
実行結果のマージ: PIT設定抜粋
Slide 77
Slide 77 text
サンプル https://github.com/tkmnzm/MultiModulePlayground ● PIT導入 ● PITレポートのマージ
Slide 78
Slide 78 text
まとめ
Slide 79
Slide 79 text
1. DI 2. テスト方針 3. メトリクス収集 まとめ ● DIのやりかたによっては 書き方や構成の変更が必要 ● 詳細はその他のDI関連 セッションで!
Slide 80
Slide 80 text
1. DI 2. テスト方針 3. メトリクス収集 まとめ ● モジュール設計時に モジュールのテスト方針を 考えてみる ● IT・UIテストもハードルが 下がりつつある
Slide 81
Slide 81 text
1. DI 2. テスト方針 3. メトリクス収集 まとめ ● 各モジュールの結果を マージする必要がある ● 不足しているテストケース を見つけてくれるPITを ご紹介
Slide 82
Slide 82 text
ご清聴ありがとうございました