iOS版KyashにMock Frameworkを導入した話 / Introducing Kyash iOS Test Cases 2020

iOS版KyashにMock Frameworkを導入した話 / Introducing Kyash iOS Test Cases 2020

3f4e0340909015791f1712c52b116da7?s=128

Hideaki Tamai

October 14, 2020
Tweet

Transcript

  1. 玉井秀明 @tamadon 2020/10/14(水) iOS Test Tea Time #1 iOS版 Kyashに

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

  3. Kyashの説明

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

    ◦ など
  5. Kyashのアーキテクチャについて

  6. MVVM+Router Presentation Layer Domain Layer Data Layer API Repository UseCase

    ViewModel Router ViewController UserDefaults KeyChain 画面遷移を管理
  7. テスト方針について

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

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

    ◦ etc...
  10. 何をテストするか?② • 期待するmethodが呼ばれるか ◦ UseCaseの呼び出し • レスポンスは期待通りか ◦ TableView/CollectionViewのDataSource ▪

    DataSourceの実装をViewModelで行っているため
  11. func testFoo() { /// Given StubとViewModelのセットアップ /// When ViewModelのメソッド呼び出し ///

    Then 値の評価 } 実装イメージ
  12. Mock Frameworkについて

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

  14. iOS Mock Frameworkの比較 ※2020.08 時点 • 条件 ◦ Swiftで書かれている ◦

    ドキュメント等の情報が豊富
  15. 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~ それなりに活発
  16. mockoloを採用することにした • 生成されたMockは最低限必要なものだけなのでシンプルで見 やすい ◦ それぞれのMethod用にHandlerが追加されるだけ • 軽量で高パフォーマンス • Class

    mockはできないがiOS版Kyashは全てProtocol化してい るので問題ない
  17. 他Frameworkの検討結果① ※個人の感想です • Cuckoo/Mockit ◦ DSLなので学習コストが高い ◦ テストの書き方がFramework依存

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

  19. mockoloの使い方

  20. mockoloの使い方① @mockableアノテーションを付けてプロトコルを定義 /// @mockable public protocol Foo { var num:

    Int { get set } func bar(arg: Float) -> String } mockoloコマンドを実行
  21. mockoloの使い方② こんな感じのファイルが Generateされる public class FooMock: Foo { init() {}

    init(num: Int = 0) { self.num = num } var numSetCallCount = 0 var underlyingNum: Int = 0 ・・・
  22. 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) }
  23. 詳しくは公式のリポジトリを参照ください https://github.com/uber/mockolo

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

  25. Thank you 25