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
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
GitHub Copilot 最新アップデート – 「一歩先」の実践活用術
moulongzhang
5
1.6k
Zenoh on Zephyr on LiteX
takasehideki
2
100
Comment regagner la souveraineté de vos données tout en étant payé grâce à Nostr !
rlifchitz
0
180
起点・思考・出力で分解する 〜PM業務の自動化設計〜
kazu_kichi_67
1
970
「ビジネスがわかるエンジニア」とは何か?
ryooob
0
260
【2026年版】 ベクトル検索とEmbedding最前線
mocobeta
23
7.3k
Agile and AI Redmine Japan 2026
hiranabe
4
460
自宅LLMの話
jacopen
1
710
SONiC実機とGNS3 SONiC VSによる事前コンフィグ検証 ― 生成AIエージェントを環境構築・検証支援に使ってみた ―
sonic
0
120
人材育成分科会.pdf
_awache
4
320
「軸足」は 固定しなくていい - 熱量と強みで描く、しなやかなキャリアの形
kakehashi
PRO
1
240
[AWS Summit Japan 2026]迷っているあなたへ_小さな一歩が、やがて自分を助けてくれる
sh_fk2
1
380
Featured
See All Featured
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
370
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.3k
Done Done
chrislema
186
16k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.5k
Everyday Curiosity
cassininazir
0
230
Fashionably flexible responsive web design (full day workshop)
malarkey
408
66k
Speed Design
sergeychernyshev
33
1.9k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.2k
Designing Experiences People Love
moore
143
24k
Designing for Timeless Needs
cassininazir
1
260
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.3k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.5k
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ͳίʔυͷςετɺͱ͔͔ͬΓʹ͘͘ײ͡Δ͔͠Ε·ͤΜ͕ɺ ࣍ͷྲྀΕͰςετΛॻ͚·͢
͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠