Testing a constraint-based layout of UIView

Testing a constraint-based layout of UIView

0e726052fdb28ba1c004aa90eccbe261?s=128

Shin Yamamoto

August 27, 2019
Tweet

Transcript

  1. Testing a constraint-based layout of UIView iOS Test Night #11

    Shin Yamamoto @scenee #ios_test_night
  2. 今日は.. • AutoLayout(constraint-based)のレイアウトテスト • 前提と手法 • UIViewにフォーカス ◦ UIViewControllerは割愛しますが、ほぼ同じ

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

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

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

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

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

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

  9. SnapshotTesting with Jest

  10. SnapshotTesting with Jest • 画面に描画する • Reactツリーを出力 • 比較 •

    差分検出
  11. ポイントは...

  12. レンダラーを信頼する

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

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

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

    tree) ◦ など
  16. もう少し詳しく説明します

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

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

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

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

  21. 何が嬉しいのか?

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

  23. Pros • 気軽にViewのテストが書ける • Viewの振る舞いをテストで記述・保存 ◦ i.e. リグレッションテストが簡単に • Viewをテスト駆動で開発・リファクタ

    ◦ i.e. frame-based layoutからの移行が楽に
  24. Cons • 描画結果が想定と異なるケースがある

  25. この前提の上で...

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

  27. MyView .containerView top bottom left right

  28. MyView .containerView top bottom left right

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

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

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

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

  33. ❌ Failed: frame値が.zero

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

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

  36. ✅ Passed: frameが期待通り更新

  37. なぜ?

  38. Layout passを手動実行している

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

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

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

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

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

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

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

  46. 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
  47. Happy Testing 質問があればぜひ懇親会で話かけてください

  48. None