Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
FBSnapshotTestCaseに助けられた話
Search
yutu
February 09, 2017
Programming
1
2.5k
FBSnapshotTestCaseに助けられた話
Kyobashi.swift x AKIBA.swift 合同勉強会
2017/02/08
yutu
February 09, 2017
Tweet
Share
More Decks by yutu
See All by yutu
コスパの良いiOS開発を求めて
yutu
1
1.9k
Other Decks in Programming
See All in Programming
創造的活動から切り拓く新たなキャリア 好きから始めてみる夜勤オペレーターからSREへの転身
yjszk
1
130
なまけものオバケたち -PHP 8.4 に入った新機能の紹介-
tanakahisateru
1
120
ブラウザ単体でmp4書き出すまで - muddy-web - 2024-12
yue4u
3
480
Stackless и stackful? Корутины и асинхронность в Go
lamodatech
0
820
RWC 2024 DICOM & ISO/IEC 2022
m_seki
0
210
バグを見つけた?それAppleに直してもらおう!
uetyo
0
180
LLM Supervised Fine-tuningの理論と実践
datanalyticslabo
7
1.3k
testcontainers のススメ
sgash708
1
120
Keeping it Ruby: Why Your Product Needs a Ruby SDK - RubyWorld 2024
envek
0
190
CQRS+ES の力を使って効果を感じる / Feel the effects of using the power of CQRS+ES
seike460
PRO
0
140
採用事例の少ないSvelteを選んだ理由と それを正解にするためにやっていること
oekazuma
2
1k
From Translations to Multi Dimension Entities
alexanderschranz
2
130
Featured
See All Featured
Designing Dashboards & Data Visualisations in Web Apps
destraynor
229
52k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
48
2.2k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
191
16k
Bash Introduction
62gerente
608
210k
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
The Power of CSS Pseudo Elements
geoffreycrofte
73
5.4k
Music & Morning Musume
bryan
46
6.2k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Optimising Largest Contentful Paint
csswizardry
33
3k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
Transcript
FBSnapshotTestCase ʹॿ͚ΒΕͨ Yuki Hirai Kyobashi.swift x AKIBA.swift ߹ಉษڧձ 2017/02/08
ฏҪ༞थͩʔʂ • 31ࡀɻطࠗ • དྷि͙Β͍ʹ͕ੜ͢Δ • RMP • iOS Engineer
FBSnapshotTestCaseʹ ॿ͚ΒΕͨΛ͠·͢
͙Β͍લɾɾɾ Φοεʂ࣍ͷϓϩδΣΫτདྷͨͧʔ ແअؾˁ طࠗˁ
͙Β͍લɾɾɾ Φοεʂ࣍ͷϓϩδΣΫτདྷͨͧʔ 0,ͬ͢ʂͲ͏͍͏ํͰ࡞͍͖ͬͯ·͢ʁ ແअؾˁ طࠗˁ
͙Β͍લɾɾɾ ͦ͏ͩͳɾɾɾ ແअؾˁ طࠗˁ
͙Β͍લɾɾɾ ࠷ۙ$MFBO4XJGUྑͦ͞͏ͩͱࢥͬͯ͊͞ɺͦΕ࠾ ༻ͭͭ͠#PMUTͱ͔͍͍ײ͡ʹͬͯॻ͜͏ͱࢥͬ ͯͯɺ͋ͬɺ͋ͱΧόϨοδશମͰͱΓͨ ͍ͱ͜ΖͩΑͶɻ͋ͱTXJGUMJOUΨονΨνʹೖΕ ͯ͞ʂ͍͍ײ͡͡ΌͶʂʁ4XJOKFDUಋೖ͠Α ͏ʂྃ݅ʹՃ͠Α͏ʂʂ ແअؾˁ طࠗˁ
͙Β͍લɾɾɾ ࠷ۙ$MFBO4XJGUྑͦ͞͏ͩͱࢥͬͯ͊͞ɺͦΕ࠾ ༻ͭͭ͠#PMUTͱ͔͍͍ײ͡ʹͬͯॻ͜͏ͱࢥͬ ͯͯɺ͋ͬɺ͋ͱΧόϨοδશମͰͱΓͨ ͍ͱ͜ΖͩΑͶɻ͋ͱTXJGUMJOUΨονΨνʹೖΕ ͯ͞ʂ͍͍ײ͡͡ΌͶʂʁ4XJOKFDUಋೖ͠Α ͏ʂྃ݅ʹՃ͠Α͏ʂʂ ͑ͬʁ3Y4XJGU͕ྑ͍ͳɾɾɾͰ࣮͋ ΔΈ͍ͨͩ͠ͳ͊ɾɾ͔͠ͳΜָ͔ͦ͠ ͏ʹͯ͠Δ͠ɾɾɾ·͍͔͊ͬ
͍ʂʂ ແअؾˁ طࠗˁ
࣮ணख طࠗˁ
࣮ணख طࠗˁ ྑ͍ײ͡
͠Βͯ͘͠ɾɾɾ ɾɾɾ ແअؾˁ طࠗˁ
͠Βͯ͘͠ɾɾɾ ͬͺ3Y4XJGUͰ͍͜͏ʂX ແअؾˁ طࠗˁ
͠Βͯ͘͠ɾɾɾ ͬͺ3Y4XJGUͰ͍͜͏ʂX ແअؾˁ طࠗˁ ͓͍X
͜͏ͯ͠ॻ͖͕͑ ͡·ͬͨ
͔͠͠৺ແ༻ʂ
͜Μͳ͜ͱ͋Ζ͏͔ͱ ൿࡦΛ४උ͍ͯͨ͠ͷͩʂ
FBSnapshotTestCase • https://github.com/facebook/ios-snapshot- test-case • UIView/CALayer ͷεφοϓγϣοτͱ͋Β͔ ͡Ί༻ҙͨ͠ը૾Λൺֱͯ͠ɺҰக͠ͳ͍ ߹ςετࣦഊʹͰ͖Δ •
XCTestCaseͷαϒΫϥε
Nimble-Snapshots • https://github.com/ashfurrow/Nimble- Snapshots • FBSnapshotTestCaseΛ Nimble ͷ matcher ͱ
ͯ͠ఆٛ
Nimble-Snapshots expect(view).to(haveValidSnapshot()) expect(view).to(haveValidSnapshot(named: "some custom name")) expect(view) == snapshot() expect(view)
== snapshot("some custom name") (view) (view, "some custom name")
import UIKit import Quick import Nimble import Nimble_Snapshots @testable import
ScreenShotExample final class ViewControllerSpec: QuickSpec { override func spec() { describe("view") { var subject: ViewController! var window: UIWindow! beforeEach { window = UIWindow() let bundle = Bundle.main let storyboard = UIStoryboard(name: "Main", bundle: bundle) subject = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController window.addSubview(subject.view) RunLoop.current.run(until: Date()) } afterEach { window = nil } it("displays correctly") { (subject) // expect(subject).toEventually(haveValidSnapshot()) } } } ʩ
import UIKit import Quick import Nimble import Nimble_Snapshots @testable import
ScreenShotExample final class ViewControllerSpec: QuickSpec { override func spec() { describe("view") { var subject: ViewController! var window: UIWindow! beforeEach { window = UIWindow() let bundle = Bundle.main let storyboard = UIStoryboard(name: "Main", bundle: bundle) subject = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController window.addSubview(subject.view) RunLoop.current.run(until: Date()) } afterEach { window = nil } it("displays correctly") { (subject) // expect(subject).toEventually(haveValidSnapshot()) } } } ʩ ύγϟϦʂ
Nimble-Snapshots
import UIKit import Quick import Nimble import Nimble_Snapshots @testable import
ScreenShotExample final class ViewControllerSpec: QuickSpec { override func spec() { describe("view") { var subject: ViewController! var window: UIWindow! beforeEach { window = UIWindow() let bundle = Bundle.main let storyboard = UIStoryboard(name: "Main", bundle: bundle) subject = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController window.addSubview(subject.view) RunLoop.current.run(until: Date()) } afterEach { window = nil } it("displays correctly") { // (subject) expect(subject).toEventually(haveValidSnapshot()) } } } ʩ
import UIKit import Quick import Nimble import Nimble_Snapshots @testable import
ScreenShotExample final class ViewControllerSpec: QuickSpec { override func spec() { describe("view") { var subject: ViewController! var window: UIWindow! beforeEach { window = UIWindow() let bundle = Bundle.main let storyboard = UIStoryboard(name: "Main", bundle: bundle) subject = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController window.addSubview(subject.view) RunLoop.current.run(until: Date()) } afterEach { window = nil } it("displays correctly") { // (subject) expect(subject).toEventually(haveValidSnapshot()) } } } ʩ
DEMO https://github.com/yutu/ScreenShotExample
ແࣄΓӽ͑ͨʂ
͔͠͠ຊʹා͍ͷɾɾɾ
࣮ɾɾɾ ແअؾˁ طࠗˁ
ͲͬͪͰͨ͠ ແअؾˁ طࠗˁ
͔ͯ͘͠ FBSnapshotTestCaseʹ ॿ͚ΒΕ·ͨ͠
FBSnapshotTestCase ͷ͍͍ͱ͜Ζ • ΞʔΩςΫνϟOSSʹґଘ͠ͳ͍ςετ͕ॻ͚Δ • අ༻ରޮՌ͕ߴ͍ • XcodeͰΧόϨοδΛܭଌͰ͖Δ • PRͰεφοϓγϣοτͷdiff͕ݟΕΔ
• CircleCI Ͱී௨ʹಈ͘ • TDDͰ͖Δ
ؾΛ͚͍ͭͨ͜ͱ • ϢχοτςετΛॻ͔ͳͯ͘ྑ͍Θ͚Ͱͳ͍ • IT͢Δ߹࣮ߦ͢ΔσόΠεͱiOS verʹҙ • UIΛར༻ͨ͠ςετ ≠ E2Eςετ
• ʮͳͥɾͲ͜·ͰςετΛॻ͔͘ʢॻ͔ͳ͍ ͔ʣʯΛৗʹҙࣝ͢Δ
ʴΞϧϑΝ • CircleCI + fastlane (scan/slather) ͰΧόϨο δܭଌ • swiftlintʢͱ͘ʹ
cyclomatic_complexityʣ • Swinject
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠