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
2.9k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
FBSnapshotTestCaseに助けられた話
Kyobashi.swift x AKIBA.swift 合同勉強会
2017/02/08
yutu
February 09, 2017
More Decks by yutu
See All by yutu
コスパの良いiOS開発を求めて
yutu
1
2.1k
Other Decks in Programming
See All in Programming
Webエンジニアなのにブラウザの仕組みがわからないので、Pythonで自作してみた
tatsuki12
4
1.6k
PHPプロジェクトの結合バランスを可視化する #php_night
kajitack
0
170
Gradle-Plugin-in-2026.pdf
ryunen344
1
130
高専、大学編入、そして未踏へ〜プロダクト開発とキャリアの歩み - Technical College, University Transfer, and On to “Mitou” / My Journey in Product Development and Career
pkmiya
0
120
Jindong: Introducing Declarative Haptics in Compose Multiplatform
l2hyunwoo
0
140
tsc.rip を支える技術 / Kyoto.なんか #8
susisu
0
4.1k
VibeCodingからAgenticWorkflowへ
starfish719
0
1k
Swift愛好会と私(ウホーイ) / Swift Fan Club and Uhooi
uhooi
0
100
freee が目指す データ マネジメント戦略 AI-Ready 時代を支える 攻めのガバナンスとは
freee
PRO
0
560
まずはプロンプトガイドを読もう、話はそれからだ
kiakiraki
1
240
まだ間に合う!今年の夏こそSchemeのマクロ展開器を完全理解!
omasanori
0
590
DynamoDBの基礎を振り返りながらベクトル検索機能を理解する
musan
3
250
Featured
See All Featured
Claude Code のすすめ
schroneko
67
230k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Leveraging Curiosity to Care for An Aging Population
cassininazir
1
480
Design in an AI World
tapps
1
290
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.3k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
680
Ruling the World: When Life Gets Gamed
codingconduct
0
310
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
400
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
400
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.4k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
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
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠