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
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
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
4
24k
20分でわかるセキュアAPI
nwiizo
1
200
Data Hubグループ 紹介資料
sansan33
PRO
0
3.1k
Redmine 7.0 新機能・機能強化解説(OSC2026京都ダイジェスト版)
vividtone
1
210
JavaScript 研修 (2026)
recruitengineers
PRO
2
460
メルカリのグローバルアプリで挑んだ AlloyDB 運用と課題解決の実践記
hatappi
0
240
つくって納得、つかって実感! 大規模言語モデルことはじめ ver2.0
recruitengineers
PRO
4
1.2k
PLATEAU で バーチャル花火大会
tatsuya1970
0
110
Pavlokで始める電撃駆動開発
sgrsn
0
180
個人OSSが、机の上から世界に広がるまでの話
shinyasaita
1
370
SO-101×VLAによる3色キューブのピック&プレース
abeja
0
160
Goでデータパイプラインを作ろう
sansantech
PRO
1
360
Featured
See All Featured
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
エンジニアに許された特別な時間の終わり
watany
108
250k
So, you think you're a good person
axbom
PRO
2
2.1k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
2
3.7k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.3k
Accessibility Awareness
sabderemane
1
170
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.4k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
650
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.5k
Ethics towards AI in product and experience design
skipperchong
2
340
A designer walks into a library…
pauljervisheath
211
24k
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ͳίʔυͷςετɺͱ͔͔ͬΓʹ͘͘ײ͡Δ͔͠Ε·ͤΜ͕ɺ ࣍ͷྲྀΕͰςετΛॻ͚·͢
͝੩ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠