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
RxTest入門
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
暗号化?某ファイルストレージはどうなるの!? 3rd Partyとうまく付き合う秘密度ラベル設計
kasada
0
210
dbt in Microsoft Fabric
ryomaru0825
0
300
IHV like なユースケースへのOpenID Connect 関連仕様の適用事例
optim
0
360
サーバー常駐型の 簡易障害調査AI エージェントを作ってみた話
masayoshi
1
390
エージェント化するAI:現在地とその先に起きる変化 / AI as Agents: The Current State and the Changes Ahead
ks91
PRO
0
160
LLMアプリ、 雰囲気で運用してませんか? 〜LLMOpsの現在地〜
taka_aki
1
570
みてねにおけるAI-DLC導入活動とAIドリブン開発の現在地/JAWS-UG AI-DLC #2
isaoshimizu
2
290
hookで自作する Claude Code の「実況ボード」
shinyasaita
2
240
カーネルまで探検して理解するふたつの自動計装
sumiyae
0
340
Claude Codeで開発以外の業務も爆速化しよう!
minorun365
PRO
11
9.1k
サービス内で複数のOP・ASを連鎖させる(OAuth/OIDC Numa (Immersion) Workshop 2026)
oidfj
PRO
0
350
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
5k
Featured
See All Featured
Typedesign – Prime Four
hannesfritz
42
3.1k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
430
New Earth Scene 8
popppiees
3
2.5k
How GitHub (no longer) Works
holman
316
150k
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3k
Design in an AI World
tapps
1
290
Between Models and Reality
mayunak
4
410
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
67
57k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
450
Done Done
chrislema
186
16k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
310
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
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ͳίʔυͷςετɺͱ͔͔ͬΓʹ͘͘ײ͡Δ͔͠Ε·ͤΜ͕ɺ ࣍ͷྲྀΕͰςετΛॻ͚·͢
͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠