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

What is iOSSnapshotTestCase

What is iOSSnapshotTestCase

Description of how to use iOSSnapshotTestCase.

Shingo Tamaki

August 24, 2018
Tweet

More Decks by Shingo Tamaki

Other Decks in Technology

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

  4. ḪΔࣄ໿Ұ೥લ

    View Slide

  5. ḪΔࣄ໿Ұ೥લ

    View Slide

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

    View Slide

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

    View Slide

  8. ͱࢥͬͨΒ...

    View Slide

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

    View Slide

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

    View Slide

  11. iOSSnapshotTestCase
    ͷ࢖͍ํ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  16. ϦϑΝϨϯεը૾ͷ࡞੒
    recordMode͕trueͷͰςετΛ࣮ߦ͢ΔͱϦϑΝϨϯε༻ը૾
    ͕ੜ੒͞Ε·͢ɻ
    override func setUp() {
    super.setUp()
    recordMode = true
    }

    View Slide

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

    View Slide

  18. ϦϑΝϨϯεը૾

    View Slide

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

    View Slide

  20. ςετ݁Ռ

    View Slide

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

    View Slide

  22. FailureDiffsΛݟͯΈΑ͏
    ├── FailureDiffs
    │ └── iOSSnapshotTestCaseSampleTests.TopScreenSnapshotTests
    │ ├── [email protected]
    │ ├── [email protected]
    │ └── [email protected]
    ├── Info.plist
    ├── ReferenceImages_64
    │ └── iOSSnapshotTestCaseSampleTests.TopScreenSnapshotTests
    │ └── [email protected]
    └── TopScreenSnapshotTests.swift

    View Slide

  23. FailureDiffsͷத਎
    FailureDiffsσΟϨΫτϦ͕ੜ੒͞Εɺ3ͭͷϑΝΠϧ͕ೖͬͯ·
    ͢
    file name description
    diff_*.png Ϗϡʔͷ෇͖߹Θͤࠩ෼
    failed_*.png ݱࡏͷϏϡʔ
    reference_*.png ࢀর༻ͷϏϡʔ(͋Δ΂͖Ϗϡʔͷը૾)

    View Slide

  24. FailureDiffsͷத਎

    View Slide

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

    View Slide

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

    View Slide

  27. Tips

    View Slide

  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,
    ]
    }

    View Slide

  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
    }
    }
    }

    View Slide

  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)
    })
    }
    }
    }

    View Slide

  31. Ϗϡʔͷঢ়ଶ࡞Γʹ͍ͭͯ
    • XCUIDevice.shared.orientationΛsetupͰ੍ޚग़དྷΔʁ
    • ࣦഊ͢Δ͜ͱ͕͋ͬͨ(or ग़དྷͳ͔ͬͨ) ΋͸΍ هԱʹͳ
    ͍
    • ࣮ߦ଎౓͸΍͸Γ஗͘ͳͬͨ
    • UIςετͷ࢓૊ΈΛ࢖͏ࣄʹҧ࿨ײΛײͨ͡
    • ૉ௚ʹΠχγϟϥΠβͰDI͢Δࣄʹͨ͠

    View Slide

  32. ɹϨϏϡʔ࣌ʹ΋໾ཱͭ
    Github΍Gitlab͸ը૾ࠩ෼ΛදࣔͰ͖ΔΑ͏ʹͳͬͨͷͰϨ
    Ϗϡʔ࣌ʹԿ͕มΘ͔ͬͨΛ֬ೝ͠΍͍͢

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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/

    View Slide