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
RxTest入門
Search
tasanobu
November 17, 2016
Technology
1.5k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
RxTest入門
第3回RxSwift勉強会で発表した資料です。
https://connpass.com/event/41478/
tasanobu
November 17, 2016
More Decks by tasanobu
See All by tasanobu
Introduction to UIStackView
tasanobu
0
250
Other Decks in Technology
See All in Technology
Minecraft JavaのMODをSwiftで作る
1mash0
0
120
消えない 動かない 効かない
yama3133
1
120
Claude in Chrome 入門 / Introduction to Claude in Chrome
cielo1985
0
640
NW運用でNWトポロジ可視化ツールに期待すること/shumoku-meetup1
corestate55
2
120
薬剤師(ドメインエキスパート)と一緒に育てる薬局向けAIアシスタント
kakehashi
PRO
2
160
Snowflakeのコスト最適化を支えるアーキテクチャ設計
ktatsuya
1
1.5k
データ界隈LT祭 第1回LT登壇
taromatsui_cccmkhd
0
680
コスト最適化の「めんどくさい」を AWS FinOps Agent でチョット楽にする
classmethod_kaz
0
330
アプリをもっと"iOSアプリっぽく"する小さな工夫 / Small Touches That Make Your App Feel More Like an iOS App
matsuji
1
740
事業課題から技術的負債に向き合う
sansantech
PRO
1
480
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
5
25k
ASTを使って影響範囲を特定する
nealle
0
180
Featured
See All Featured
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
370
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.2k
Amusing Abliteration
ianozsvald
1
290
Bash Introduction
62gerente
615
220k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
Navigating Team Friction
lara
192
16k
From π to Pie charts
rasagy
0
360
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.3k
Color Theory Basics | Prateek | Gurzu
gurzu
0
460
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
6
1.2k
Transcript
RxTest ೖ 2016/11/17 RxSwiftษڧձ #3
Kazunobu Tasaka About Me @tasanobu
ຊͷ༰ • RxTest ͷ֓ཁ • RxTestΛ༻ͨ͠ςετίʔυͷॻ͖ํ • ·ͱΊ
RxTest ͷ֓ཁ
RxTest ͱ • RxSwift ϨϙδτϦͰఏڙ͞Ε͍ͯΔςετϑϨʔϜ ϫʔΫ • RxSwift ࣗମͷςετʹར༻͞Ε͍ͯΔ •
Cocoapods ͔ΒΠϯετʔϧՄೳ target 'RxTest-SampleTests' do pod 'RxTest', '~> 3.0' pod 'RxSwift', '~> 3.0' pod 'RxCocoa', '~> 3.0' end
RxTest ͷओཁͳΫϥε • TestScheduler • RxTestͷத৺తͳΫϥε • ࣮࣌ؒͱΓ͞ΕͨԾ࣌ؒΛ࣮ • Ծ࣌ؒʹج͖ͮ
• ΠϕϯτΛൃੜͤ͞Δ • ҙΞΫγϣϯΛ࣮ߦ͢Δ (subscribe, on ͳͲ) • `TestableObservable` `TestableObserver` ͷϑΝΫτϦϝιουΛ࣋ͭ • TestableObservable • ࢦఆͨ͠Ծ࣌ؒʹΠϕϯτΛൃੜ͢ΔObservable • ObservableͷϥΠϑαΠΫϧʹൃੜͨ͠subscriptionΛه • TestableObserver • ड৴ͨ͠ΠϕϯτͱͦͷԾ࣌ؒΛηοτʹอ࣋͢ΔObserver
࣮ྫΛݟ͍͖ͯ·͠ΐ͏
mapΦϖϨʔλͷςετʢ؆қ൛ʣ RxSwift: Observable+StandardSequenceOperatorsTest.swift https://github.com/ReactiveX/RxSwift/blob/master/Tests/RxSwiftTests/Observable+StandardSequenceOperatorsTest.swift#L754-L782 func test_map() { // 1.
Ծ࣌ؒ 0 Λࢦఆ͠TestSchedulerΛੜ let scheduler = TestScheduler(initialClock: 0) // 2. TestableObservable<Int> Λ `Ծ࣌ؒ` `` Λࢦఆͯ͠ੜ let xs = scheduler.createHotObservable([ next(150, 1), // ୈҰҾ: Ծ࣌ؒ, ୈೋҾ: next(210, 0), next(240, 4), completed(300) ]) // 3. TestableObserver<Int> Λੜ let observer = scheduler.createObserver(Int.self)
RxSwift ͷ map ͷςετΛ؆ૉԽͨ͠ྫ // 4. Ծ࣌ؒ `200` ʹ `observer`
Λ `xs` ʹ subscribe ͤ͞Δ scheduler.scheduleAt(200) { xs.map { $0 * 2 } .subscribe(observer) .addDisposableTo(self.disposeBag) } // 5. schedulerΛ։࢝ scheduler.start() let expectedEvents = [ next(210, 0 * 2), next(240, 4 * 2), completed(300) ] /// 6-1. TestableObserver ͕ड৴ͨ͠ΠϕϯτΛݕূ XCTAssertEqual(observer.events, expectedEvents) let expectedSubscriptions = [ Subscription(200, 300) ] /// 6-2. TestableObservable ͕ subscribe/unsubscribe ͞ΕͨԾ࣌ؒΛݕূ XCTAssertEqual(xs.subscriptions, expectedSubscriptions) }
ʙ࣮ફฤʙ GithubͷϑΥϩϫʔݕࡧը໘ ViewModel
ViewModel class SearchViewModel { let disposeBag = DisposeBag() // .loading,
.loaded, .error var state: Variable<State> = Variable(.loaded([])) var users: Variable<[User]> = Variable([]) let client: Client init(client: Client) { self.client = client } func searchFollowers(ofUser user: String) { state.value = .loading client.fetchFollowers(ofUser: user) .subscribe { event in switch event { case .next(let users) : self.state.value = .loaded(users) self.users.value = users case .error(let e): self.state.value = .error(e as? Client.Error ?? .unknown) self.users.value = [] default: // ignore `.completed` break } } .addDisposableTo(disposeBag) } }
ςετ؍ͰͷϙΠϯτ 1. Client ΛΠχγϟϥΠβͰड͚औΔ 2. searchFollowers() Ͱ Client.fetchFollowers()
Λίʔϧ͢ Δ init(client: Client) { self.client = client } func searchFollowers(ofUser user: String) { state.value = .loading client.fetchFollowers(ofUser: user) .subscribe { event in … } .addDisposableTo(disposeBag) }
Mock Client class MockClient: Client { // ௨৴݁Ռͱͯ͠͏Observable let response:
TestableObservable<[User]> init(response: TestableObservable<[User]>) { self.response = response super.init() } override func fetchFollowers(ofUser user: String) -> Observable<[User]> { // `response` ΛΓͱͯ͠return return response.asObservable() } }
ςετ: SearchViewModel.state ʢ௨৴ޭ࣌ʣ • stateϓϩύςΟ searchFollowers() ͷݺͼग़͠ʹΑΓมԽ͢Δɻ func test_state_when_searchFollowers_succeeded() {
let users = [User(id: 12091114, name: "tunepolo")] // 1. TestableObserverΛੜ let observer = scheduler.createObserver(State.self) // 2. ௨৴݁Ռͱͯ͠͏ColdͳObservableΛੜ let xs = scheduler.createColdObservable([ next(100, users) ]) // 3. ObservableΛͬͯMockClientΛੜ let client = MockClient(response: xs) // 4. MockClientΛͬͯSearchViewModelΛੜ let viewModel = SearchViewModel(client: client)
ςετ: SearchViewModel.state ͷঢ়ଶมԽ // 5. Ծ࣌ؒ 100: TestableObservableΛsubscribe scheduler.scheduleAt(100) {
viewModel.state.asObservable() .subscribe(observer) .addDisposableTo(self.disposeBag) } // 6. Ծ࣌ؒ 200: viewModelͷsearchFollowers()Λίʔϧ scheduler.scheduleAt(200) { viewModel.searchFollowers(ofUser: "tasanobu") } // 7. schedulerΛ։࢝ scheduler.start() // 8. ظͱͷൺֱ let expectedEvents = [ next(100, State.loaded([])), next(200, State.loading), next(300, State.loaded(users)) // ☝ 300 = subscribe@200 + 100 ɹɹɹɹɹɹɹ// Cold ObservableͷͨΊ ] XCTAssertEqual(observer.events, expectedEvents)
·ͱΊ
RxTest: ςετίʔυͷྲྀΕ 1. TestScheduler Λੜ 2. ݕূ͍ͨ͠ΠϕϯτΛTestableObservableͱͯ͠ੜ 3. ॲཧ݁ՌΛอ࣋͢ΔTestableObserverΛੜ 4.
TestableObserverʹTestableObservableΛsubscribeͤ͞Δ 5. TestSchedulerΛελʔτ 6. TestableObserver.events TestableObservable.subscriptions Λݕূ Reactiveͳίʔυͷςετɺͱ͔͔ͬΓʹ͘͘ײ͡Δ͔͠Ε·ͤΜ͕ɺ ࣍ͷྲྀΕͰςετΛॻ͚·͢
͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠