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.8k
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
2.1k
Other Decks in Programming
See All in Programming
encoding/json/v2のUnmarshalはこう変わった:内部実装で見る設計改善
kurakura0916
0
350
Claude Codeセッション現状確認 2026福岡 / fukuoka-aicoding-00-beacon
monochromegane
4
400
Go Conference mini in Sendai 2026 : Goに新機能を提案し実装されるまでのフロー徹底解説
yamatoya
0
540
Railsの気持ちを考えながらコントローラとビューを整頓する/tidying-rails-controllers-and-views-as-rails-think
moro
4
380
今、アーキテクトとして 品質保証にどう関わるか
nealle
0
210
RubyとGoでゼロから作る証券システム: 高信頼性が求められるシステムのコードの外側にある設計と運用のリアル
free_world21
0
230
Codex の「自走力」を高める
yorifuji
0
1k
Unity6.3 AudioUpdate
cova8bitdots
0
120
「やめとこ」がなくなった — 1月にZennを始めて22本書いた AI共創開発のリアル
atani14
0
360
Claude Code の Skill で複雑な既存仕様をすっきり整理しよう
yuichirokato
1
320
米国のサイバーセキュリティタイムラインと見る Goの暗号パッケージの進化
tomtwinkle
2
510
手戻りゼロ? Spec Driven Developmentとは@KAG AI week
tmhirai
1
170
Featured
See All Featured
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.2k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.4k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.1k
Fireside Chat
paigeccino
42
3.8k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
280
Building a Modern Day E-commerce SEO Strategy
aleyda
45
8.8k
Chasing Engaging Ingredients in Design
codingconduct
0
130
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
0
220
Building Flexible Design Systems
yeseniaperezcruz
330
40k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
630
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
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠