Slide 1

Slide 1 text

Testing a constraint-based layout of UIView iOS Test Night #11 Shin Yamamoto @scenee #ios_test_night

Slide 2

Slide 2 text

今日は.. ● AutoLayout(constraint-based)のレイアウトテスト ● 前提と手法 ● UIViewにフォーカス ○ UIViewControllerは割愛しますが、ほぼ同じ

Slide 3

Slide 3 text

なぜUIViewレイアウトを テストしたいのか?

Slide 4

Slide 4 text

XCTestでレイアウトを ユニットテストしたいから

Slide 5

Slide 5 text

XCTestでレイアウトをユニットテストしたい ● OSSのメンテンスなどで必要に QAで時間が溶ける!

Slide 6

Slide 6 text

XCTestでレイアウトをユニットテストしたい ● OSSのメンテンスなどで必要に QAで時間が溶ける! ● 安心して追加変更、デグレ防止

Slide 7

Slide 7 text

XCTestでレイアウトをユニットテストしたい ● OSSのメンテンスなどで必要に QAで時間が溶ける! ● 安心して追加変更、デグレ防止 ● 素早い開発フィードバックループ Design Develop Unit testing

Slide 8

Slide 8 text

どうしたらレイアウトを ユニットテストできるか?

Slide 9

Slide 9 text

SnapshotTesting with Jest

Slide 10

Slide 10 text

SnapshotTesting with Jest ● 画面に描画する ● Reactツリーを出力 ● 比較 ● 差分検出

Slide 11

Slide 11 text

ポイントは...

Slide 12

Slide 12 text

レンダラーを信頼する

Slide 13

Slide 13 text

レンダラーが あるレイアウトを期待通り描画する と仮定すること!

Slide 14

Slide 14 text

コントロールできない領域を テスト対象から除外する

Slide 15

Slide 15 text

UIKitのレンダラーを信頼する ● あるレイアウト結果が、期待通りに描画されると想定 ● レイアウト結果とは ○ UIViewの各プロパティ値(frameなど) ○ View hierarchy(Layer tree) ○ など

Slide 16

Slide 16 text

もう少し詳しく説明します

Slide 17

Slide 17 text

High Performance Auto Layout: https://developer.apple.com/videos/play/wwdc2018/220

Slide 18

Slide 18 text

High Performance Auto Layout: https://developer.apple.com/videos/play/wwdc2018/220 Layout pass Update pass Display pass

Slide 19

Slide 19 text

High Performance Auto Layout: https://developer.apple.com/videos/play/wwdc2018/220 draw(_:) layoutSubviews(_:) updateConstraints(_:)

Slide 20

Slide 20 text

High Performance Auto Layout: https://developer.apple.com/videos/play/wwdc2018/220 draw(_:)はテストしない layoutSubviews(_:) updateConstraints(_:)

Slide 21

Slide 21 text

何が嬉しいのか?

Slide 22

Slide 22 text

レイアウトのパラメーター化 ● レイアウトを各パラメーターの集合として処理 ● 各パラメーターの変化をXCTestで評価

Slide 23

Slide 23 text

Pros ● 気軽にViewのテストが書ける ● Viewの振る舞いをテストで記述・保存 ○ i.e. リグレッションテストが簡単に ● Viewをテスト駆動で開発・リファクタ ○ i.e. frame-based layoutからの移行が楽に

Slide 24

Slide 24 text

Cons ● 描画結果が想定と異なるケースがある

Slide 25

Slide 25 text

この前提の上で...

Slide 26

Slide 26 text

早速テストを書いてみましょう! コード例ではわかりやすさのため使ってませんが、 swift-snaphost-testing が便利 https://github.com/pointfreeco/swift-snapshot-testing

Slide 27

Slide 27 text

MyView .containerView top bottom left right

Slide 28

Slide 28 text

MyView .containerView top bottom left right

Slide 29

Slide 29 text

‍レイアウト更新をテスト

Slide 30

Slide 30 text

‍レイアウト更新をテスト

Slide 31

Slide 31 text

‍レイアウト更新をテスト

Slide 32

Slide 32 text

‍レイアウト更新をテスト

Slide 33

Slide 33 text

❌ Failed: frame値が.zero

Slide 34

Slide 34 text

‍レイアウト更新をテスト

Slide 35

Slide 35 text

‍レイアウト更新をテスト

Slide 36

Slide 36 text

✅ Passed: frameが期待通り更新

Slide 37

Slide 37 text

なぜ?

Slide 38

Slide 38 text

Layout passを手動実行している

Slide 39

Slide 39 text

Layout passを手動実行している setNeedsLayoutはLayout passをlayoutIfNeededで実行するために

Slide 40

Slide 40 text

Mysteries of Auto Layout, Part 2: https://developer.apple.com/videos/play/wwdc2015/219

Slide 41

Slide 41 text

1. 制約の変更 2. setNeedsLayout() + layoutIfNeeded() 3. frameを評価 XCTestでのレイアウトテスト方法

Slide 42

Slide 42 text

● Intrinsic Content Sizeに応じたテスト可 ● Unsatisfiable constraintsエラーもコンソールに出力 補足

Slide 43

Slide 43 text

簡単ですね! あくまで導入です!でも導入が大事。

Slide 44

Slide 44 text

✅ Passed: UIWindow + MainRunLoop ✏ Frameworkでは、Host Application追加不要

Slide 45

Slide 45 text

まとめ: XCTestでレイアウトテストをするには? ● UIKitのレンダラーを信頼する ● レイアウトをパラメーター化して評価 ● レイアウト更新するにはLayout passを手動実行

Slide 46

Slide 46 text

References ○ https://jestjs.io/docs/en/snapshot-testing Snapshot Testing · Jest ○ https://github.com/pointfreeco/swift-snapshot-testing swift-snapshot-testing ○ https://developer.apple.com/videos/play/wwdc2015/219 Mysteries of Auto Layout, Part 2 ○ https://developer.apple.com/videos/play/wwdc2018/220 High Performance Auto Layout ○ http://tech.gc.com/demystifying-ios-layout/ Demystifying iOS Layout

Slide 47

Slide 47 text

Happy Testing 質問があればぜひ懇親会で話かけてください

Slide 48

Slide 48 text

No content