Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Rui Peres: Testing FRP Code
Search
Realm
July 08, 2016
Technology
86
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Rui Peres: Testing FRP Code
Realm
July 08, 2016
More Decks by Realm
See All by Realm
WWDC 2017 Review
realm
0
2.2k
Xcode shortcuts
realm
0
4.8k
Self Branding with GitHub
realm
0
4.4k
Realm Mobile Platform overview and demo
realm
0
2.1k
Realm advanced topics and demo
realm
0
2k
Realm introduction Seoul meetup 10
realm
0
2.2k
Stuart Hall: How I got 2.3 Million App Downloads
realm
0
2k
James Majors: What the Swiftly Func?
realm
1
4.3k
Simina Pasat: Continuous everything for iOS apps
realm
0
670
Other Decks in Technology
See All in Technology
新機種発売前に見直そう!端末移行で再ログインが要るアプリ・要らないアプリは何が違うのか 〜シームレスに再開できる設計と実装〜
zozotech
PRO
0
120
アプリログインとWeb認証基盤をつなぐ ASWebAuthenticationSession 作法
shimastripe
1
240
2026-09-10 【Snowflake World Tour Tokyo 2026】dbt Core と Snowflake で実現する多層的なデータガバナンス / Multi-Layered Data Governance Powered by dbt Core and Snowflake
civitaspo
0
360
range over func 2年間の軌跡 Issue #56413 はGoのエコシステムをどう変えたか
ryujicre8ive
0
120
Oracle Cloud Infrastructure IaaS 新機能アップデート 2026/6 - 2026/8
oracle4engineer
PRO
0
190
Slack上でインフラをトラブルシュートする! Agentic Platform Engineeringの第一歩
teru0x1
4
1.5k
Snowflakeで実現する全社横断の顧客の声(VOC)分析・活用基盤@Snowflake World Tour Tokyo 2026
yuto16
0
200
omasushiというライブラリを作った
polidog
PRO
0
210
Deploying a Full-Stack Bun-Native Framework on Cloudflare Workers
7nohe
0
150
Claude in Chrome 入門 / Introduction to Claude in Chrome
cielo1985
0
620
銀行勘定系システムにおける開発プロセス刷新×AIによる環境モダナイゼーション / Development Process Transformation and AI-Driven Environment Modernization
muit
0
660
NW運用でNWトポロジ可視化ツールに期待すること/shumoku-meetup1
corestate55
2
120
Featured
See All Featured
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
560
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
4
630
Leo the Paperboy
mayatellez
9
2.3k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
530
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.1k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
370
A Soul's Torment
seathinner
7
3.6k
Utilizing Notion as your number one productivity tool
mfonobong
4
590
A designer walks into a library…
pauljervisheath
211
25k
Transcript
1
BUENOS DÍAS BARCELONA !☀# 2
FRP && TESTING 3
But before we start... 4
SMALL STORY... ! 5
WAY BACK IN 2013... ⏰ 6
FRP + RAC + OBJC ! 7
8
9
10
11
12
13
FRP 101 ! 14
FAMILIAR CONCEPTS... ! 15
KVO + NSOperation + ✨ 16
KVO 17
MutableProperty<T> 18
let foo = MutableProperty(1) // 1. observe foo foo.signalProducer.startWithNext {
newFooValue in print(newFooValue) // prints "1" } // 2. modifiy foo's value foo.value = 2 // 3. prints "2" 19
NSOperation 20
SignalProducer<T, E: ErrorType> 21
let networkCall: SignalProducer<NSData, NSError> = ... let parser: NSData ->
[Painting] = ... let paintingsProducer = networkCall.map(parser) .startOn(QueueScheduler()) 22
paintingsProducer.startWithNext { paintings in print(paintings) // [!, "] } paintingsProducer.on(
failure: { error in // handle error }, next: { paintings in print(paintings) // [!, "] }) .start() 23
✨ 24
25
EXAMPLES... ! 26
Form Validation 27
28
let email: MutableProperty<String> = emailTextField.rex_text let password: MutableProperty<String> = passwordTextField.rex_text
let isValid: (String, String) -> Bool = ... let areCredentialsValid = combineLatest(email.producer, password.producer).map(isValid) loginButton.rex_enabled <~ areCredentialsValid 29
30
Puzzle ! 31
32
33
A plan... ! 34
35
let drinks = SignalProducer<[String], NoError>(value: ["!","!"]) let areSober: [String] ->
Bool = ... let gamePlan = drinks .concat(drinks.delay(7.5)) .concat(timer(5).flatMapLatest { _ in drinks }.takeWhile(areSober)) 36
TESTING FRP ! 37
Discrete 38
func testNumberPaintings() { let expectation = self.expectationWithDescription("Expect to have 2
paintings") defer { self.waitForExpectationsWithTimeout(1.0, handler: nil) } paintingsViewModel.paintingsProducer.startWithNext { paintings in XCTAssertEqual(paintings.count, 2) expectation.fulfill() } } 39
func testNumberPaintings() { let result: Result<[Painting], Error>? = paintingsViewModel.paintingsProducer.first() XCTAssertEqual(result?.value?.count,
2) } 40
Continuous 41
final class StubbedNextValues<T: Equatable> { private var nextValues: [T] private
let expectation: XCTestExpectation init(nextValues: [T] , expectation: XCTestExpectation) { self.nextValues = nextValues self.expectation = expectation } func handleNextValue(nextValue: T) -> Void { guard !nextValues.isEmpty else { fatalError("Can't handle \(nextValue)") } let stubbedValue = nextValues.removeFirst() XCTAssertEqual(stubbedValue, nextValue) if nextValues.isEmpty { expectation.fulfill() } } } 42
let producer: SignalProducer<Int, NoError> = ... let stubbedNextValues = StubbedNextValues(nextValues:
[1, 2, 3, 4], expectation: expectation) producer.startWithNext(stubbed.handleNextValue) 43
FRP takes a while to get used to... ! 44
...testing FRP code is as difficult as you want it
to be ! 45
THANKS @peres 46
47