What is iOSSnapshotTestCase

What is iOSSnapshotTestCase

Description of how to use iOSSnapshotTestCase.

Db5cf21a75ebe2484b95ea9dec5f573b?s=128

Shingo Tamaki

August 24, 2018
Tweet

Transcript

  1. iOSSnapshotTestCase ͰϏϡʔͷςετΛߦ͏

  2. ࣗݾ঺հ • ۄ৓৴ޛ • iOS Engineer • iOSDC2018Ͱελοϑ͠·͢

  3. iOSSnapshotTestCaseͱ͸ View based testingΛߦ͏ͨΊͷπʔϧ ݩFBSnapshotTestCaseͰɺ΋ͱ΋ͱ͸Facebook੡ Ϗϡʔͷը૾Λ෇͖߹ΘͤͯมߋҰக͢Δ͔Λςετ͢Δػೳ ͕͋Γ·͢ɻ

  4. ḪΔࣄ໿Ұ೥લ

  5. ḪΔࣄ໿Ұ೥લ

  6. ผͷखஈΛݕ౼ͯ͠ΈͨΓ WiremockΛ࢖ͬͨUIςετ https://speakerdeck.com/tamaki/wiremockdexing-uuitesuto

  7. σϝϦοτ΋͋Γ·ͨ͠ • XCUITestͷ࣮ߦ࣌ؒ • XCUITestͰը໘ͷঢ়ଶΛ࡞Δखؒ

  8. ͱࢥͬͨΒ...

  9. iOSSnapshotTestCaseͱͯ͠෮׆ Uber͕Ҿ͖ܧ͙ܗͰ෮׆ https://github.com/uber/ios-snapshot-test-case

  10. ࠶ͼ࢖͍࢝ΊΔࣄʹ͠·ͨ͠ɻ

  11. iOSSnapshotTestCase ͷ࢖͍ํ

  12. Πϯετʔϧ target "Tests" do use_frameworks! pod 'iOSSnapshotTestCase' end

  13. ઃఆ • FBREFERENCEIMAGEDIR: $(SOURCEROOT)/$ (PROJECT_NAME)Tests/ReferenceImages • IMAGEDIFFDIR: $(SOURCEROOT)/$(PROJECTNAME)Tests/ FailureDiffs

  14. ςετ࡞੒ FBSnapshotTestCaseΛܧঝͨ͠ςετέʔεΛ࡞੒͠·͢ɻ class iOSSnapshotTestCaseSampleTests: FBSnapshotTestCase { }

  15. ςετϝιου࡞੒ FBSnapshotVerifyViewͰର৅ͷϏϡʔΛνΣοΫ͠·͢ɻ ର৅ͷϏϡʔͷαΠζ͸CGRect(x:y:width:height)ͳͲͰࢦఆ͠ ͓͖ͯ·͠ΐ͏ɻ view.frame = CGRect(x: 0, y: 0,

    width: 768, height: 1024) FBSnapshotVerifyView(view, identifier: "view id")
  16. ϦϑΝϨϯεը૾ͷ࡞੒ recordMode͕trueͷͰςετΛ࣮ߦ͢ΔͱϦϑΝϨϯε༻ը૾ ͕ੜ੒͞Ε·͢ɻ override func setUp() { super.setUp() recordMode =

    true }
  17. ϦϑΝϨϯεը૾ ReferenceImages_64ͷ഑Լʹςετλʔήοτ໊.ςετέʔ ε໊ͷσΟϨΫτϦͱɺ ͦͷԼʹ෇͖߹ΘͤʹඞཁͱͳΔࢀর༻ը૾͕࡞੒͞Ε·͢ɻ iOSSnapshotTestCaseSampleTests/ ├── Info.plist ├── ReferenceImages_64 │

    └── iOSSnapshotTestCaseSampleTests.TopScreenSnapshotTests │ └── testTopScreen@2x.png └── TopScreenSnapshotTests.swift
  18. ϦϑΝϨϯεը૾

  19. ςετͷ࣮ߦ recordModeΛfalseʹ͢ΔࣄΛ๨Εͳ͍Α͏ʹɻ override func setUp() { super.setUp() recordMode = false

    }
  20. ςετ݁Ռ

  21. ը໘͕มߋ͠ςετΛ࣮ߦ͢Δͱ... ૂ͍௨Γςετ͸ࣦഊ͠·ͨ͠Ͷʁ

  22. FailureDiffsΛݟͯΈΑ͏ ├── FailureDiffs │ └── iOSSnapshotTestCaseSampleTests.TopScreenSnapshotTests │ ├── diff_testTopScreen@2x.png │

    ├── failed_testTopScreen@2x.png │ └── reference_testTopScreen@2x.png ├── Info.plist ├── ReferenceImages_64 │ └── iOSSnapshotTestCaseSampleTests.TopScreenSnapshotTests │ └── testTopScreen@2x.png └── TopScreenSnapshotTests.swift
  23. FailureDiffsͷத਎ FailureDiffsσΟϨΫτϦ͕ੜ੒͞Εɺ3ͭͷϑΝΠϧ͕ೖͬͯ· ͢ file name description diff_*.png Ϗϡʔͷ෇͖߹Θͤࠩ෼ failed_*.png ݱࡏͷϏϡʔ

    reference_*.png ࢀর༻ͷϏϡʔ(͋Δ΂͖Ϗϡʔͷը૾)
  24. FailureDiffsͷத਎

  25. ࢀর༻ͷը૾ͷ࠶ੜ੒ ઌ΄Ͳͷςετ͸Ϗϡʔʹࠩ෼͕͋Γςετ͸ࣦഊ͠·ͨ͠ ͕ɺ૝ఆͨ͠௨Γͳ༁Ͱ͔͢Βɺ࠶౓ࢀর༻ͷը૾Λొ࿥͠௚ ͠·͢ɻ

  26. جຊతͳ࢖͍ํ(·ͱΊ) ͜ͷΑ͏ͳ࡞ۀΛ܁Γฦ͢ࣄͰҎԼͷΑ͏ͳԸܙΛड͚Δ͜ͱ ͕Ͱ͖·͢ɻ • ҙਤ͠ͳ͍ը໘่ΕΛݕ஌ग़དྷΔ • PR࣌ʹϦϑΝϨϯεը૾ؚ͕·ΕΔࣄͰը໘ͷ֬ೝָ͕ʹͳ Δ

  27. Tips

  28. ෳ਺αΠζ΁ͷରԠ ϏϡʔͷαΠζ΍ॎԣͷରԠͳͲ΋ͨ͘͠ͳΓ·͢ΑͶʁ ྫ͑͹ྻڍܕͰσόΠεαΠζΛఆٛ enum DeviceSize: String { case size_10_5_inch =

    "10.5inch" case size_12_9_inch = "12.9inch" static func all() -> [DeviceSize] { return [ .size_10_5_inch, .size_12_9_inch, ] }
  29. ෳ਺αΠζ΁ͷରԠ ޲͖ຖͷ֤σόΠεͷαΠζ(Rect)Λฦ͢ϝιουΛੜ΍ͨ͠Γ ͢ΔͱָʹͳΓͦ͏Ͱ͢ɻ func frame(with orientation: UIInterfaceOrientation) -> CGRect {

    switch (self, orientation) { case (.size_10_5_inch, .portrait): return CGRect(x: 0, y: 0, width: 834, height: 1112) case (.size_10_5_inch, .landscapeLeft): return CGRect(x: 0, y: 0, width: 1112, height: 834) case (.size_12_9_inch, .portrait): return CGRect(x: 0, y: 0, width: 1024, height: 1366) case (.size_12_9_inch, .landscapeLeft): return CGRect(x: 0, y: 0, width: 1366, height: 1024) default: return CGRect.zero } } }
  30. ෳ਺αΠζ΁ͷରԠ FBSnapshotVerifyView͸جຊతʹ1ϏϡʔͣͭVerify͍ͯ͘͠ͷ Ͱ͕͢ɺSnapshotVerifyViewAllSizeΛ࡞ͬͯෳ਺αΠζΛҰ ؾʹςετग़དྷΔΑ͏ʹͨ͠Γ͍ͯ͠·͢ɻ extension FBSnapshotTestCase { public func SnapshotVerifyViewAllSize(_

    vc: UIViewController, identifier: String = "", orientation: UIInterfaceOrientation) { for size in DeviceSize.all() { XCTContext.runActivity(named: "\(identifier)_\(size.rawValue)", block: { activity in let view = vc.view! view.frame = size.frame(with: orientation) FBSnapshotVerifyView(view, identifier: activity.name) }) } } }
  31. Ϗϡʔͷঢ়ଶ࡞Γʹ͍ͭͯ • XCUIDevice.shared.orientationΛsetupͰ੍ޚग़དྷΔʁ • ࣦഊ͢Δ͜ͱ͕͋ͬͨ(or ग़དྷͳ͔ͬͨ) ΋͸΍ هԱʹͳ ͍ •

    ࣮ߦ଎౓͸΍͸Γ஗͘ͳͬͨ • UIςετͷ࢓૊ΈΛ࢖͏ࣄʹҧ࿨ײΛײͨ͡ • ૉ௚ʹΠχγϟϥΠβͰDI͢Δࣄʹͨ͠
  32. ɹϨϏϡʔ࣌ʹ΋໾ཱͭ Github΍Gitlab͸ը૾ࠩ෼ΛදࣔͰ͖ΔΑ͏ʹͳͬͨͷͰϨ Ϗϡʔ࣌ʹԿ͕มΘ͔ͬͨΛ֬ೝ͠΍͍͢

  33. ݒ೦ • ը໘਺͕ଟ͍ΞϓϦͷ৔߹ͷϦϙδτϦͷαΠζ૿Ճ • Uber͕ϝϯς΍ΊΔ • ࠓ౓͸ࣗ෼Ͱר͖औͬͯϝϯς͢Δؾ࣋ͪΛ࣋ͱ͏͔ͳ ͱɻ

  34. ·ͱΊ • UIςετ΍E2EͰ͸ͳ͘ϏϡʔͷΈΛςετ͍ͨ͠৔߹ʹ͓ ͢͢ΊͰ͢ • ௨ৗͷ୯ମςετΑΓ࣌ؒ͸͔͔Γ·͢ • ϏϡʔͷϓϩύςΟͳͲʹΞΫηεͯ͠ςετ͢Δํ๏΋ ͋Δ

  35. Ҏ্ɺ͝੩ௌ͋Γ͕ͱ͏ ͍͟͝·ͨ͠ɻ

  36. ࢀߟ https://github.com/facebookarchive/ios-snapshot-test-case https://github.com/facebookarchive/ios-snapshot-test-case/ issues/227#issuecomment-335175385 https://www.objc.io/issues/15-testing/snapshot-testing/