Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Unit Test with SwiftyMocky

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.
Avatar for Yosuke Imairi Yosuke Imairi
September 24, 2019

Unit Test with SwiftyMocky

Mockolo のほうがおすすめ : https://github.com/uber/mockolo

How to use SwiftyMocky for iOS app unit tests
example: https://github.com/imairi/SwiftyMockyDemo

Avatar for Yosuke Imairi

Yosuke Imairi

September 24, 2019
Tweet

More Decks by Yosuke Imairi

Other Decks in Technology

Transcript

  1. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved ⾃⼰紹介

    2 Yosuke Imairi • JapanTaxi (2017.5 -) • iOS app Developer
  2. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved iOSDC2019でブース出展しました

    3 JapanTaxiのサービス全体のデモ - 「JapanTaxi」アプリでタクシーを 呼ぶ - ドライバーが応答 - 降⾞時の⽀払い
  3. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved iOSDC2019でブース出展しました

    4 「JapanTaxi」アプリの技術スタックペーパー - iOS, Android で利⽤している⾔語 - 導⼊しているアーキテクチャやライブラリ
  4. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved iOSDC2019でブース出展しました

    5 「JapanTaxi」アプリの技術スタックペーパー - iOS, Android で利⽤している⾔語 - 導⼊しているアーキテクチャやライブラリ
  5. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved SwiftyMocky

    6 ⁃ SwiftのProtocolをモック化できるライブラリ ⁃ SouceryのAutoMockableを利⽤ ⁃ ジェネリクスにも対応 ⁃ Given: モックで返す値を設定 ⁃ Verify: モック内のプロパティ/メソッド呼び出し回数を取得 ⁃ Perform: モック内のメソッド処理後の追加処理
  6. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved モックの準備 ①

    7 ⁃ モック化したいProtocolをAutoMockableに準拠させる protocol ToBeMocked: AutoMockable { // ... } //sourcery: AutoMockable protocol ToBeMocked { // ... } ⁃ アノテーションをはるだけでもOK
  7. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved モックの準備 ①

    8 ⁃ メインターゲット protocol User { var name: String { get } var age: Int { get } func profile() -> String func update(age: Int) func update(name: String, completion:(() -> Void)) } ⁃ テストターゲット //sourcery: AutoMockable extension User {} ⇒ User をモック化の対象に
  8. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved モックの準備 ②

    10 ⁃ Mockfile sourceryCommand: null SwiftyMockyDemoTests: sources: include: - ./SwiftyMockyDemo - ./SwiftyMockyDemoTests output: ./SwiftyMockyDemoTests/Mock.generated.swift targets: - SwiftyMockyDemoTests testable: - SwiftyMockyDemo import: - Foundation
  9. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved モックの準備 ③

    11 ⁃ Mock(Mock.generated.swift)の⽣成 $ swiftymocky generate
  10. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved モックの準備 ③

    12 ⁃ Mock.generated.swift // MARK: - User open class UserMock: User, Mock { … public var name: String { get { invocations.append(.p_name_get); return __p_name ?? givenGetterValue(.p_name_get, "UserMock - stub value for name was not defined") } @available(*, deprecated, message: "Using setters on readonly variables is deprecated, and will be removed in 3.1. Use Given to define stubbed property return value.") set { __p_name = newValue } } … open func profile() -> String { addInvocation(.m_profile) let perform = methodPerformValue(.m_profile) as? () -> Void perform?() …
  11. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved モックの準備 ③

    13 ⁃ もし、なにか問題があれば… $ swiftymocky doctor
  12. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved UnitTestでモックを使う ①

    14 ⁃ 「Protocol名 + Mock」クラス ⁃ モックに対して情報を与える(Given) let user = UserMock() user.given(.name(getter: "imairi")) user.given(.age(getter: 32)) user.given(.profile(willReturn: "いまいりようすけ 32歳"))
  13. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved UnitTestでモックを使う ②

    15 ⁃ モックで動作確認をする(Verify) ⁃ モック内のプロパティ/メソッドが呼ばれた回数を検査 ⁃ Countにはさまざまな種類が⽤意されている user.verify(.profile(), count: 3) user.verify(.profile(), count: .never) user.verify(.profile(), count: .more(than: 2)) user.verify(.profile(), count: .custom({ count -> Bool in guard self.user.age < 30 && count == 1 else { return true } return false }))
  14. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved UnitTestでモックを使う ②

    16 ⁃ モックで動作確認をする(Verify) ⁃ 引数を考慮した検査も⾏える // 引数もチェックする user.verify(.update(age: .value(33)), count: 1) // 引数はチェックしない user.verify(.update(age: .any), count: 1)
  15. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved UnitTestでモックを使う ③

    17 ⁃ モックのメソッドが呼ばれた後の処理(Perform) // UnitTest user.perform(.update(name: .any, completion: .any, perform: { (name, completion) in completion() })) // UserProtocol func update(name: String, completion:(() -> Void)) ⁃ Closureを引数にとるメソッドをモック化し、UnitTestか ら操作できない場合はPerformを使う必要あり
  16. Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved まとめ

    19 ⁃ SwiftyMockyでProtocolのモック化がかんたんにできる ⁃ Protocolを多⽤しているプロジェクトに向いている ⁃ メソッドの呼ばれた回数の検査でテストの幅も広がる ⁃ モックがかんたんに作れるとテストを書く気になれる
  17. จষɾը૾౳ͷ಺༰ͷແஅసࡌٴͼෳ੡౳ͷߦҝ͸͝ԕྀ͍ͩ͘͞ɻ Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved

    ˟102-0094ɹ౦ژ౎ઍ୅ా۠لඌҪொ3-12 3-12 Kioicho Chiyoda-ku, Tokyo 102-0094 Japan TEL 03-6265-6265ɹFAX 03-3239-8115 www.japantaxi.co.jp