SlideShare a Scribd company logo
Snapshot
Testing
Lars Lockefeer
Snapshot Testing @ CocoaheadsNL
struct Person {
let name: String
let age: Int?
}
struct Person {
let name: String
let age: Int?
init?(fromJSON json: [String: AnyObject]) {
guard let name = json["name"] as? String else {
return nil
}
self.name = name
self.age = json["age"] as? Int
}
}
func testValidJsonResultsInCorrectModel() {
let person = Person(fromJSON: [
"name": "Lars Lockefeer",
"age": 42
])
XCTAssertNotNil(person)
XCTAssertEqual(person?.name, "Lars Lockefeer")
XCTAssertEqual(person?.age, 42)
}
func testValidJsonResultsInCorrectModel2() {
let person = Person(fromJSON: [
"name": "Lars Lockefeer"
])
XCTAssertNotNil(person)
XCTAssertEqual(person?.name, "Lars Lockefeer")
XCTAssertNil(person?.age)
}
func testInvalidJsonResultsInNil() {
let person = Person(fromJSON: [
"age": 42
])
XCTAssertNil(person)
}
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
Agile
development
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
!
Faster & Better
Implementation
Continuous
Verification
Snapshot Testing @ CocoaheadsNL
Documentation
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
Snapshot Testing @ CocoaheadsNL
How?
Cocoa Design
Patterns
class MyTableViewCell {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var photoImageView: UIImageView!
@IBOutlet weak var ratingControl: RatingControl!
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
/// Dequeue cell etc.
let product = products[indexPath.row]
cell.nameLabel.text = product.name
cell.photoImageView.image = product.photo
cell.ratingControl.rating = product.rating
}
func testProductCellLayout() {
let view = ProductCell()
view.nameLabel.text = "Peanut butter"
view.photoImageView.image = UIImage(named: "placeholder")
view.ratingControl.rating = 5
validateView(view)
}
Snapshot Testing @ CocoaheadsNL
Testing View Controllers is hard.
-- Everybody, always, everywhere.
Snapshot Testing @ CocoaheadsNL
class ProductDetailsViewController: UIViewController {
private let titleLabel: UILabel
// ... More properties ...
init(urlSession: NSURLSession, moc: NSManagedObjectContext, cache: DiskCache) {
self.urlSession = urlSession
// ...
}
func viewDidLoad() {
// ...
session.dataTaskWithURL("https://domain.tld/api/products/123") { data, response, error in
// ...
titleLabel = data["title"]
}
}
}
→ Image
→ Title
→ Price
→ Tags
Snapshot Testing @ CocoaheadsNL
class ProductDetailsViewModel {
typealias Observer = (UIImage, String, [String], Money) -> ()
private var loadObservers: [Observer]
init(urlSession: NSURLSession, moc: NSManagedObjectContext, cache: DiskCache) {
urlSession.dataTaskWithURL("https://domain.tld/api/products/123") { data, response, error in
// ...
for observer in self.loadObservers {
observer(data["image"], data["title"], data["tags"], data["price"])
}
}
}
func subscribe(observer: Observer) {
loadObservers.append(observer)
}
}
class ProductDetailsViewController: UIViewController {
private let titleLabel: UILabel
// ... More properties ...
init(viewModel: ProductDetailsViewModel) {
self.viewModel = viewModel
// ...
}
func viewDidLoad() {
// ...
viewModel.subscribe { image, title, tags, price in
titleLabel.title = title
// ...
}
}
}
typealias Observer = (UIImage, String, [String], Money) -> ()
protocol ProductDetailsViewModelType {
func subscribe(observer: Observer)
}
class ProductDetailsViewController: UIViewController {
private let titleLabel: UILabel
// ... More properties ...
init(viewModel: ProductDetailsViewModelType) {
// ...
}
}
extension ProductDetailsViewModel: ProductDetailsViewModelType {}
struct Mock: ProductDetailsViewModelType {
func subscribe(observer: Observer) {
observer(UIImage(named: "placeholder"), "Test Product", ["Tag 1", "Tag 2", "Tag 3"], Money(cents: 999))
}
}
func testProductDetailViewControllerLayout() {
let viewModel = Mock()
let viewController = ProductDetailsViewController(viewModel: viewModel)
validateViewOfViewController(viewController)
}
struct Mock: ProductDetailsViewModelType {
let image: UIImage
let title: String
let tags: [String]
let price: Money
func subscribe(observer: Observer) {
observer(image, title, tags, price)
}
}
func testProductDetailViewControllerLayout() {
let viewModel = Mock(
image: UIImage(named: "placeholder"),
title: "Test Product",
tags: ["Tag 1, Tag 2, Tag 3"]
price: Money(cents: 999)
)
let viewController = ProductDetailsViewController(viewModel: viewModel)
validateViewOfViewController(viewController)
}
func testProductDetailViewControllerEdgeCases() {
let viewModel = Mock(
image: UIImage(named: "placeholder"),
title: "A really long name, that won't fit the view. Let's see what it does.",
tags: ["Tag 1", "Tag 2", "Tag 3", "Tag 4", "Tag 5", ..., "Tag 99", "Tag 100"]
price: Money(cents: 999999999)
)
let viewController = ProductDetailsViewController(viewModel: viewModel)
validateViewOfViewController(viewController)
}
!
Recap
!
→ FBSnapshotTestCase
→ Kaleidoscope
→ Second Curtain
Thanks for listening!
Questions?
lars.lockefeer@teampicnic.com
@larslockefeer

More Related Content

PPTX
The zen of async: Best practices for best performance
PDF
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
PDF
The Ring programming language version 1.7 book - Part 41 of 196
PPT
Xm lparsers
PPTX
Prototype Framework
ZIP
Easy undo.key
PPTX
PDF
The Ring programming language version 1.8 book - Part 80 of 202
The zen of async: Best practices for best performance
«Objective-C Runtime в примерах» — Алексей Сторожев, e-Legion
The Ring programming language version 1.7 book - Part 41 of 196
Xm lparsers
Prototype Framework
Easy undo.key
The Ring programming language version 1.8 book - Part 80 of 202

What's hot (20)

PDF
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
PDF
JavaScript Fundamentals with Angular and Lodash
PDF
Functionality Focused Code Organization
PDF
Using Templates to Achieve Awesomer Architecture
PDF
OSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
PPT
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
PDF
The Ring programming language version 1.9 book - Part 53 of 210
PDF
The Ring programming language version 1.5.2 book - Part 37 of 181
PPTX
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
PDF
Design Patterns Reconsidered
PPTX
Hacking JavaFX with Groovy, Clojure, Scala, and Visage
PPTX
Windows ストアーアプリで SQLite を使ってみよう
PDF
The Ring programming language version 1.8 book - Part 49 of 202
PPTX
11. session 11 functions and objects
PDF
A evolução da persistência de dados (com sqlite) no android
PPTX
Working With JQuery Part1
PPTX
Web Development Course - JQuery by RSOLUTIONS
PDF
The Ring programming language version 1.10 book - Part 64 of 212
PDF
I os 04
Functional Object-Oriented Imperative Scala / 関数型オブジェクト指向命令型 Scala by Sébasti...
JavaScript Fundamentals with Angular and Lodash
Functionality Focused Code Organization
Using Templates to Achieve Awesomer Architecture
OSDC.fr 2012 :: Cascalog : progammation logique pour Hadoop
Cleaner APIs, Cleaner UIs with Visage (33rd Degrees)
The Ring programming language version 1.9 book - Part 53 of 210
The Ring programming language version 1.5.2 book - Part 37 of 181
JavaFX 2.0 With Alternative Languages - Groovy, Clojure, Scala, Fantom, and V...
Design Patterns Reconsidered
Hacking JavaFX with Groovy, Clojure, Scala, and Visage
Windows ストアーアプリで SQLite を使ってみよう
The Ring programming language version 1.8 book - Part 49 of 202
11. session 11 functions and objects
A evolução da persistência de dados (com sqlite) no android
Working With JQuery Part1
Web Development Course - JQuery by RSOLUTIONS
The Ring programming language version 1.10 book - Part 64 of 212
I os 04
Ad

Similar to Snapshot Testing @ CocoaheadsNL (20)

KEY
Backbone js
PDF
droidparts
PDF
Clean Javascript
PDF
Managing parallelism using coroutines
PDF
Js 单元测试框架介绍
KEY
Scala on Your Phone
PDF
Taming Core Data by Arek Holko, Macoscope
PPTX
Getting started with Elasticsearch and .NET
PDF
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
PDF
Realm to Json & Royal
PDF
Introduction kot iin
PPTX
Тарас Олексин - Sculpt! Your! Tests!
PDF
前端MVC 豆瓣说
PDF
The Ring programming language version 1.5.4 book - Part 44 of 185
PDF
Android Design Patterns
KEY
Object-Oriented JavaScript
KEY
Object-Oriented Javascript
PDF
Google App Engine Developer - Day3
PDF
Слава Бобик «NancyFx для самых маленьких»
PDF
ScalikeJDBC Tutorial for Beginners
Backbone js
droidparts
Clean Javascript
Managing parallelism using coroutines
Js 单元测试框架介绍
Scala on Your Phone
Taming Core Data by Arek Holko, Macoscope
Getting started with Elasticsearch and .NET
Kotlin for Android Developers - Victor Kropp - Codemotion Rome 2018
Realm to Json & Royal
Introduction kot iin
Тарас Олексин - Sculpt! Your! Tests!
前端MVC 豆瓣说
The Ring programming language version 1.5.4 book - Part 44 of 185
Android Design Patterns
Object-Oriented JavaScript
Object-Oriented Javascript
Google App Engine Developer - Day3
Слава Бобик «NancyFx для самых маленьких»
ScalikeJDBC Tutorial for Beginners
Ad

Recently uploaded (20)

PPT
Project quality management in manufacturing
PDF
SM_6th-Sem__Cse_Internet-of-Things.pdf IOT
PPTX
Construction Project Organization Group 2.pptx
PDF
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
PDF
R24 SURVEYING LAB MANUAL for civil enggi
PPTX
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
PDF
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
PPTX
Foundation to blockchain - A guide to Blockchain Tech
PDF
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
PDF
PPT on Performance Review to get promotions
PPTX
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
PDF
TFEC-4-2020-Design-Guide-for-Timber-Roof-Trusses.pdf
PDF
Unit I ESSENTIAL OF DIGITAL MARKETING.pdf
PPTX
additive manufacturing of ss316l using mig welding
PDF
Well-logging-methods_new................
PPTX
Safety Seminar civil to be ensured for safe working.
PDF
Embodied AI: Ushering in the Next Era of Intelligent Systems
PDF
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
PDF
The CXO Playbook 2025 – Future-Ready Strategies for C-Suite Leaders Cerebrai...
PPT
Introduction, IoT Design Methodology, Case Study on IoT System for Weather Mo...
Project quality management in manufacturing
SM_6th-Sem__Cse_Internet-of-Things.pdf IOT
Construction Project Organization Group 2.pptx
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
R24 SURVEYING LAB MANUAL for civil enggi
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
Foundation to blockchain - A guide to Blockchain Tech
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
PPT on Performance Review to get promotions
MET 305 2019 SCHEME MODULE 2 COMPLETE.pptx
TFEC-4-2020-Design-Guide-for-Timber-Roof-Trusses.pdf
Unit I ESSENTIAL OF DIGITAL MARKETING.pdf
additive manufacturing of ss316l using mig welding
Well-logging-methods_new................
Safety Seminar civil to be ensured for safe working.
Embodied AI: Ushering in the Next Era of Intelligent Systems
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
The CXO Playbook 2025 – Future-Ready Strategies for C-Suite Leaders Cerebrai...
Introduction, IoT Design Methodology, Case Study on IoT System for Weather Mo...

Snapshot Testing @ CocoaheadsNL