Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ReactorKit Testability

USAMI Kosuke
February 15, 2019

ReactorKit Testability

USAMI Kosuke

February 15, 2019
Tweet

More Decks by USAMI Kosuke

Other Decks in Programming

Transcript

  1. Design Goal • Testability : View ͱϩδοΫͷ෼཭ • Start Small

    : ΞϓϦͷҰ෦͚ͩͰ΋ద༻Ͱ͖Δ • Less Typing : ίʔυΛෳࡶʹ͠ͳ͍
  2. View ͱ Reactor • View ͷ੹຿ (1) • UI ૢ࡞

    → Action ͱͯ͠ Reactor ʹ౉͢ • Reactor ͷ੹຿ • Action → ॲཧΛߦ͍ State Λੜ੒͢Δ • View ͷ੹຿ (2) • State → UI ʹදࣔ͢Δ
  3. ੹຿ͷ෼཭ • UIViewController ʹ͸ View ͷ੹຿͚ͩΛ࣋ͨͤΔ • Reactor ͸ผΦϒδΣΫτͱͯ͠෼཭ʢͳ͓ɺReactor ͸

    UIKit ͸࢖Θͳ͍ʣ • ͜ΕʹΑΓ Testability ͕޲্͢Δ • ࠓճ͸ಛʹ View ͷ Testability ΛݟͯΈΔ
  4. View ϓϩτίϧ class MyViewController: View { func bind(reactor: MyReactor) {

    // ͜͜Ͱ Reactor ͱͷόΠϯσΟϯάΛߦ͏ // RxSwift Λ׆༻ } }
  5. Reactor ϓϩτίϧ class MyReactor: Reactor { enum Action { case

    myAction case myActionWithArg(Int) } struct State { var myValue1 = "" var myValue2 = false } }
  6. View ͷόΠϯσΟϯά : Action func bind(reactor: MyReactor) { myButton.rx.tap .map

    { Reactor.Action.myAction } .bind(to: reactor.action) .disposed(by: self.disposeBag) ʢͳ͓ɺreactor.action ͸ ActionSubjectʣ
  7. View ͷόΠϯσΟϯά : State func bind(reactor: MyReactor) { reactor.state .map

    { $0.myValue1 } .bind(to: myLabel.rx.text) .disposed(by: self.disposeBag) ʢͳ͓ɺreactor.state ͸ Observableʣ
  8. Reactor ͷॲཧ : mutate() • Action Λड͚औͬͯ Observable<Mutation> Λฦ͢ •

    ۩ମతͳॲཧʢWeb API ࣮ߦɺσʔλϕʔεΞΫηεɺͳͲʣ Λߦ͏ Observable Λੜ੒͢Δ • ࣮ࡍʹॲཧΛߦ͏͔Ͳ͏͔ͷ൑அͳͲ͸ Reactor ͷ໾໨ • ͜ΕʹΑΓɺView ଆͰ͸ Action Λੜ੒͢Δ͔Ͳ͏͔Λ൑ அ͠ͳ͍ͨΊɺView ͷ࣮૷͕όΠϯσΟϯά͚ͩͰ͢Ή
  9. Reactor ͷॲཧ : reduce() • Mutation ͱલͷ State Λड͚औͬͯ State

    Λฦ͢ • ॲཧͷ݁Ռͱલͷঢ়ଶΛߟྀͯ࣍͠ͷঢ়ଶΛܾΊΔͷ͕໾໨ • ͜ΕʹΑΓɺView ଆͰ͸લͷঢ়ଶΛߟྀ͢Δͱ͍ͬͨॲཧ͕ ෆཁʹͳΔͨΊɺView ͷ࣮૷͕όΠϯσΟϯά͚ͩͰ͢Ή
  10. View ͷςετ : Action • ίʔυͰ UI ૢ࡞Λൃੜͤ͞Δ • myButton.sendActions(for

    .touchUpInside) • ͦͷ݁Ռͱͯ͠ɺReactor ʹ Action ΦϒδΣΫτ͕౉͞Ε ͨ͜ͱΛ֬ೝ͍ͨ͠ • Ͳ͏΍ͬͯʁ ʹ Reactor ͷελϒΛ༻ҙ͢Ε͹͍͍ • ࣮͸ ReactorKit Ͱ͸ελϒ͕͢Ͱʹ༻ҙ͞Ε͍ͯΔ
  11. View ͷςετ : Action func testMyAction() { let reactor =

    MyReactor() reactor.stub.isEnabled = true let view = MyView() view.reactor = reactor view.myButton.sendActions(for .touchUpInside) XCTAssertEqual(reactor.stub.actions.last, .myAction) }
  12. View ͷςετ : State • ΍͸Γ Reactor ͷελϒΛ׆༻͢Δ • ίʔυͰ

    Reactor ͷ State มԽΛى͜͢ • ͦͷ݁Ռͱͯ͠ɺUI ද͕ࣔมߋ͞Εͨ͜ͱΛ֬ೝ͢Δ
  13. View ͷςετ : State func testMyAction() { let reactor =

    MyReactor() reactor.stub.isEnabled = true let view = MyView() view.reactor = reactor reactor.stub.state.value = MyReactor.State(myValue1: "abc") XCTAssertEqual(view.myLabel.text, "abc") }
  14. View ͷςετ·ͱΊ • Կ͕ςετͰ͖ͨͷ͔ʁ : View ͕੹຿ΛՌ͍ͨͯ͠Δ͜ͱ • View ͷ࣮૷ͱͯ͠͸όΠϯσΟϯά͕ͪΌΜͱͰ͖͍ͯΔ͜

    ͱ • ͦ΋ͦ΋ςετඞཁʁ : Testability ޲্ͷͨΊγϯϓϧ ͳΦϒδΣΫτʹͳͬͨ݁Ռɺ୯७͗ͯ͢ςετෆཁͰ͸ͱ͍ ͏Ϩϕϧʹ • ࣮ࡍʹςετίʔυΛॻ͔͘Ͳ͏͔͸έʔεόΠέʔε
  15. Reactor ͷ୯ମςετʢུ֓ʣ • ʮͦͷΦϒδΣΫτͷ੹຿ΛՌ͍ͨͯ͠Δ͔ʯΛςετ͢Δ • Reactor ͷ੹຿ : Action →

    State • ίʔυͰ Action Λൃੜͤͯ͞ɺState มߋΛ֬ೝ͢Δ • Reactor ͸ View ΁ͷґଘ͕ͳ͍ͨΊɺಠཱͯ͠ςετՄೳ
  16. Reactor ͷ୯ମςετʢུ֓ʣ • Reactor ͷதͰ Web API ࣮ߦɺσʔλϕʔεΞΫηεɺͳ Ͳ͕͋Δͱ୯ମςετ͠ʹ͘͘ͳΔ •

    ͦ͜ͰɺͦΕΒΛ Service ͱͯ͠ Reactor ͷ֎ʹ੾Γग़͢ • Service ΛελϒԽ͢Δ͜ͱͰ Reactor ͕୯ମςετՄೳ
  17. ·ͱΊ • ෳ਺ͷ੹຿Λ͕࣋ͪͪͳ UIViewController ʹ͍ͭͯɺ ReactorKit Ͱ View ͱ Reactor

    ʹ੹຿Λ෼཭ͨ͠ • ͜ΕʹΑΓɺView ΍ Reactor ͕ςετՄೳʹͳͬͨ