Share
Embed
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
Yosuke Imairi
September 24, 2019
Transcript
20 slides
-
Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved Unit
Test with SwiftyMocky -
Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved ⾃⼰紹介
2 Yosuke Imairi • JapanTaxi (2017.5 -) • iOS app Developer -
Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved iOSDC2019でブース出展しました
3 JapanTaxiのサービス全体のデモ - 「JapanTaxi」アプリでタクシーを 呼ぶ - ドライバーが応答 - 降⾞時の⽀払い -
Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved iOSDC2019でブース出展しました
4 「JapanTaxi」アプリの技術スタックペーパー - iOS, Android で利⽤している⾔語 - 導⼊しているアーキテクチャやライブラリ -
Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved iOSDC2019でブース出展しました
5 「JapanTaxi」アプリの技術スタックペーパー - iOS, Android で利⽤している⾔語 - 導⼊しているアーキテクチャやライブラリ -
Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved SwiftyMocky
6 ⁃ SwiftのProtocolをモック化できるライブラリ ⁃ SouceryのAutoMockableを利⽤ ⁃ ジェネリクスにも対応 ⁃ Given: モックで返す値を設定 ⁃ Verify: モック内のプロパティ/メソッド呼び出し回数を取得 ⁃ Perform: モック内のメソッド処理後の追加処理 -
Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved モックの準備 ①
7 ⁃ モック化したいProtocolをAutoMockableに準拠させる protocol ToBeMocked: AutoMockable { // ... } //sourcery: AutoMockable protocol ToBeMocked { // ... } ⁃ アノテーションをはるだけでもOK -
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 をモック化の対象に -
Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved モックの準備 ②
9 ⁃ Mockfileの作成 $ swiftymocky setup -
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 -
Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved モックの準備 ③
11 ⁃ Mock(Mock.generated.swift)の⽣成 $ swiftymocky generate -
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?() … -
Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved モックの準備 ③
13 ⁃ もし、なにか問題があれば… $ swiftymocky doctor -
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歳")) -
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 })) -
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) -
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を使う必要あり -
Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved Sample
codes 18 ⁃ github.com/imairi/SwiftyMockyDemo -
Proprietary and Confidential ©2017 JapanTaxi, Inc. All Rights Reserved まとめ
19 ⁃ SwiftyMockyでProtocolのモック化がかんたんにできる ⁃ Protocolを多⽤しているプロジェクトに向いている ⁃ メソッドの呼ばれた回数の検査でテストの幅も広がる ⁃ モックがかんたんに作れるとテストを書く気になれる -
จষɾը૾ͷ༰ͷແஅసࡌٴͼෳͷߦҝ͝ԕྀ͍ͩ͘͞ɻ 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