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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
技術記事、AIに書かせるか、自分で書くか? 〜それでも私が自分の手で書く理由〜 / #QiitaConference
jnchito
2
1.4k
コンテキストの使い捨てをやめる — ビジネスルール駆動開発と miko —
ioki
0
210
Claspは野良GASの夢をみるか
takter00
0
200
LLM本来の能力を解き放つサンドボックス技術とAI民主化への適用
yukukotani
3
4.2k
Lemonade + Foundry Toolkit でお手軽アプリ開発
seosoft
1
350
Agentic UI
manfredsteyer
PRO
0
170
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
130
JavaDoc 再入門
nagise
1
360
A2UI という光を覗いてみる
satohjohn
1
140
TAKTでAI駆動開発の品質を設計する
j5ik2o
7
1.3k
正しくソフトウェアを作る、前提を疑うための認知の視点 / doubt-premise
minodriven
21
6.7k
気づいたらRubyで100作品 ー クリエイティブコーディングが生活の一部になるまで / 100 Ruby Sketches Later: How Creative Coding Became Part of My Life
chobishiba
3
580
Featured
See All Featured
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
260
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
490
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
270
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
The Power of CSS Pseudo Elements
geoffreycrofte
82
6.3k
Information Architects: The Missing Link in Design Systems
soysaucechin
0
970
Java REST API Framework Comparison - PWX 2021
mraible
34
9.4k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
330
KATA
mclloyd
PRO
35
15k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
590
The Curious Case for Waylosing
cassininazir
1
390
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
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠