Slide 1

Slide 1 text

玉井秀明 @tamadon 2020/10/14(水) iOS Test Tea Time #1 iOS版 Kyashに Mock Frameworkを 導入した話

Slide 2

Slide 2 text

@tamadon @tamadon3776 ・2020/01 Kyash入社。iOSチームのテックリードをしています ・マジック:ザ・ギャザリングというカードゲームをかれこれ 20年以上プレイしています

Slide 3

Slide 3 text

Kyashの説明

Slide 4

Slide 4 text

● Visaブランドで発行されるプリペイドカードを簡単に作れる ● チャージ元として以下が利用可能 ○ 銀行口座 ○ クレジットカード ○ セブン銀行ATM ○ など

Slide 5

Slide 5 text

Kyashのアーキテクチャについて

Slide 6

Slide 6 text

MVVM+Router Presentation Layer Domain Layer Data Layer API Repository UseCase ViewModel Router ViewController UserDefaults KeyChain 画面遷移を管理

Slide 7

Slide 7 text

テスト方針について

Slide 8

Slide 8 text

ViewModelを優先的に ・ビジネスロジックがViewModelに集中している ・ロジックが肥大化しやすい→バグが起きやすい

Slide 9

Slide 9 text

何をテストするか?① ● Observable、BehaviorRelay、Driverに期待するイベントが流れ てくるか ○ Binding ○ 通信状態の監視 ○ フォーム入力時のバリデーション ○ etc...

Slide 10

Slide 10 text

何をテストするか?② ● 期待するmethodが呼ばれるか ○ UseCaseの呼び出し ● レスポンスは期待通りか ○ TableView/CollectionViewのDataSource ■ DataSourceの実装をViewModelで行っているため

Slide 11

Slide 11 text

func testFoo() { /// Given StubとViewModelのセットアップ /// When ViewModelのメソッド呼び出し /// Then 値の評価 } 実装イメージ

Slide 12

Slide 12 text

Mock Frameworkについて

Slide 13

Slide 13 text

下記理由から必要と判断 ● UseCaseが100以上あるので1つずつMockを書くのも大変 ● UseCaseの実装が変わるたびにMockを修正するのも大変 ○ 自動でGenerateされるようにしたい

Slide 14

Slide 14 text

iOS Mock Frameworkの比較 ※2020.08 時点 ● 条件 ○ Swiftで書かれている ○ ドキュメント等の情報が豊富

Slide 15

Slide 15 text

GitHub上の情報 Name Size Star 開発時期 メンテナンス mockolo 716KB 242 2019.01~ それなりに活発 Cuckoo 2.28MB 1.3K 2016.10~ それなりに活発 Mockit 230KB 107 2016.05~ あまり活発ではない SwiftyMocky 17.59MB 694 2017.05~ それなりに活発

Slide 16

Slide 16 text

mockoloを採用することにした ● 生成されたMockは最低限必要なものだけなのでシンプルで見 やすい ○ それぞれのMethod用にHandlerが追加されるだけ ● 軽量で高パフォーマンス ● Class mockはできないがiOS版Kyashは全てProtocol化してい るので問題ない

Slide 17

Slide 17 text

他Frameworkの検討結果① ※個人の感想です ● Cuckoo/Mockit ○ DSLなので学習コストが高い ○ テストの書き方がFramework依存

Slide 18

Slide 18 text

他Frameworkの検討結果② ※個人の感想です ● SwiftMocky ○ あまり良く見ていないのですが、Given, Verify, Performとい う大文字始まりのメソッドに違和感があり見送り

Slide 19

Slide 19 text

mockoloの使い方

Slide 20

Slide 20 text

mockoloの使い方① @mockableアノテーションを付けてプロトコルを定義 /// @mockable public protocol Foo { var num: Int { get set } func bar(arg: Float) -> String } mockoloコマンドを実行

Slide 21

Slide 21 text

mockoloの使い方② こんな感じのファイルが Generateされる public class FooMock: Foo { init() {} init(num: Int = 0) { self.num = num } var numSetCallCount = 0 var underlyingNum: Int = 0 ・・・

Slide 22

Slide 22 text

mockoloの使い方③ GenerateされたMockクラスを呼んでXCTAsertで評価する func testMock() { let mock = FooMock(num: 5) XCTAssertEqual(mock.numSetCallCount, 1) mock.barHandler = { arg in return String(arg) } XCTAssertEqual(mock.barCallCount, 1) }

Slide 23

Slide 23 text

詳しくは公式のリポジトリを参照ください https://github.com/uber/mockolo

Slide 24

Slide 24 text

今後の展望 ● カバレッジの拡充 ○ 導入していくつかのViewModelのテストを書いた状態 ● ノウハウの共有 ○ 試行錯誤中なので知見が溜まったらまた発表したい

Slide 25

Slide 25 text

Thank you 25