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
Rui Peres: Testing FRP Code
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Realm
July 08, 2016
Technology
79
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.7k
Self Branding with GitHub
realm
0
4.3k
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
660
Other Decks in Technology
See All in Technology
Databricks における 生成AIガバナンスの実践
taka_aki
1
370
AIっぽい文章を採点して人間らしく直すアプリを作ってみた
yama3133
2
110
Oracle Cloud Infrastructure IaaS 新機能アップデート 2026/3 - 2026/5
oracle4engineer
PRO
1
240
Claude Code×Terraform IaC テンプレート駆動開発
itouhi
1
460
Agentic Defenseとともにセキュリティエンジニアが輝き続けるには / How Security Engineers Can Keep Excelling with Agentic Defense
yuj1osm
0
140
EventBridge Connection
_kensh
5
680
スキルと MCP ツール、責務をどう分けるか? AI が迷わないインターフェース設計の戦略
cdataj
1
790
MIERUNE JCT 発表資料「宇宙から伊能忠敬ごっこ」
syuchimu
0
200
MCP Appsを作ってみよう
iwamot
PRO
4
330
Building applications in the Gemini API family.
line_developers_tw
PRO
0
2.5k
DevOps Agentで始めるAWS運用 〜フロンティアエージェントが変える運用の現場〜
nyankotaro
1
360
AI Engineering Summit Tokyo 2026 AIの前に、やることがある 〜医療データ企業の4フェーズ〜
dtaniwaki
0
2.4k
Featured
See All Featured
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
390
Accessibility Awareness
sabderemane
1
130
Why Our Code Smells
bkeepers
PRO
340
58k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.9k
What does AI have to do with Human Rights?
axbom
PRO
1
2.2k
Everyday Curiosity
cassininazir
0
230
Done Done
chrislema
186
16k
How GitHub (no longer) Works
holman
316
150k
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.9k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
600
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
160
The SEO Collaboration Effect
kristinabergwall1
1
480
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