Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- RxCocoa
- swift documentation
- rxswift
- HIG
- 리펙터링
- UITextView
- 클린 코드
- uitableview
- Protocol
- 리팩토링
- UICollectionView
- collectionview
- ribs
- tableView
- Observable
- SWIFT
- Human interface guide
- Refactoring
- MVVM
- map
- Clean Code
- 스위프트
- Xcode
- uiscrollview
- 애니메이션
- swiftUI
- 리펙토링
- clean architecture
- combine
- ios
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 2. ReactorKit - 테스트 방법 (Storyboard 사용, IBOutlet 테스트 방법) 본문
Architecture (swift)/ReactorKit
[iOS - swift] 2. ReactorKit - 테스트 방법 (Storyboard 사용, IBOutlet 테스트 방법)
jake-kim 2021. 11. 30. 22:252. ReactorKit - 테스트 방법 (Storyboard 사용, IBOutlet 테스트 방법)
3. ReactorKit - `TaskList 구현`, 템플릿 (template), 비동기 처리 transform(mutation:)
4. ReactorKit - `TaskEdit 구현`, 화면전환, 데이터 전달
* 해당 코드는 ReactorKit git repository 코드를 참고하였습니다.
* Unit Test가 중요한 이유, 클린 코드: https://ios-development.tistory.com/770
* Counter 예제 코드: https://github.com/JK0369/ExReactorKit/tree/BaseComponent
ReactorKit 테스트
- View -> Reactor
- View에서 Reactor에 Action값을 잘 넘기고 있는지 확인
(view에서 보낸 action이 Reactor에 잘 전달 되었는지 확인)
- View에서 Reactor에 Action값을 잘 넘기고 있는지 확인
- Reactor -> View
- View에서 Reactor를 잘 구독하고 있는지 확인
(Reactor에서 상태 변화가 일어난 경우, View에 반영되는지 확인)
- View에서 Reactor를 잘 구독하고 있는지 확인
- Reactor
- action을 받으면 비즈니스 로직(Mutation)이 잘 처리되어 State값이 기대하는 값으로 변경되는지 확인
1. 테스트 View -> Reactor
View에서 Reactor에 Action값을 잘 넘기고 있는지 확인
- 테스트 준비
- sut: System Under Test (테스트 대상의 변수명)
- View를 구성할 때 storyboard를 이용했으므로, storyboard 객체 선언 `sut`
import XCTest
@testable import ExCounter
class ExCounterTests: XCTestCase {
let sut = UIStoryboard(name: "Counter", bundle: nil)
}
- 테스트 코드 메소드 시그니처 작성
- 감소 버튼을 탭한 경우, 작업단위 (Mutation) 값이 decrease로 잘 들어오는지 테스트
func testAction_whenDidTapDecreaseButtonInView_thenMutationIsDecreaseInReactor()
- 구현
- 주의해야할 점은 ViewController를 storyboard 인스턴스로 생성 후, loadViewIfNeeded()를 호출해주어야 IBOutlet 인스턴스가 생성되므로 호출
func testAction_whenDidTapDecreaseButtonInView_thenMutationIsDecreaseInReactor() {
// Given
let counterReactor = CounterViewReactor()
counterReactor.isStubEnabled = true
let counterViewController = sut.instantiateViewController(withIdentifier: "Counter") as! CounterViewController
counterViewController.loadViewIfNeeded() // IBOutlet과 Action을 구성하기 위해서 호출
counterViewController.reactor = counterReactor
// When
counterViewController.decreaseButton.sendActions(for: .touchUpInside)
// Then
XCTAssertEqual(counterReactor.stub.actions.last, .decrease)
}
2. 테스트 Reactor -> View
View에서 Reactor를 잘 구독하고 있는지 확인
- 메소드 시그니처 작성
- Reactor에서 loding 상태가 바뀐 경우, View에도 반영되는지 확인
func testState_whenChangeLoadingStateToTrueInReactor_thenActivityIndicatorViewIsAnimatingInView()
- 구현
func testState_whenChangeLoadingStateToTrueInReactor_thenActivityIndicatorViewIsAnimatingInView() {
// Given
let counterReactor = CounterViewReactor()
counterReactor.isStubEnabled = true
let counterViewController = sut.instantiateViewController(withIdentifier: "Counter") as! CounterViewController
counterViewController.loadViewIfNeeded()
counterViewController.reactor = counterReactor
// When
counterReactor.stub.state.value = CounterViewReactor.State(value: 0, isLoading: true)
// Then
XCTAssertEqual(counterViewController.activityIndicatorView.isAnimating, true)
}
3. 테스트 Reactor
1) action을 받으면 비즈니스 로직(Mutation)이 잘 처리되어 State값이 기대하는 값으로 변경되는지 확인
- 메소드 시그니처 작성
- Reactor에서 특정 action을 주고, 내부적으로 mutate(), reduce()를 통해서 state값이 기대하는 값으로 변경되는지 확인
func testReactor_whenExcuteIncreaseButtonTapActionInView_thenStateIsLoadingInReactor()
- 구현
func testReactor_whenExcuteIncreaseButtonTapActionInView_thenStateIsLoadingInReactor() {
// Given
let reactor = CounterViewReactor()
// When
reactor.action.onNext(.increase)
// Then
XCTAssertEqual(reactor.currentState.isLoading, true)
}
2) 비동기처리인 경우 테스트 방법 - increase 액션이 발생했을 때, 최종적으로 value값이 변화하는지 테스트
- 메소드 시그니처 작성
- Reactor에서 특정 action을 주었을때, value값이 변화하는지 테스트
func testReactor_whenExecuteIncreaseButtonTapActionInView_thenStateValueIsChanged()
- 구현
// RxSwift관련 코드도 추가
// import RxSwift
// var disposeBag = DisposeBag()
func testReactor_whenExecuteIncreaseButtonTapActionInView_thenStateValueIsChanged() {
// Given
let reactor = CounterViewReactor()
let expectation = XCTestExpectation(description: "Test Description")
reactor.state.map(\.value)
.distinctUntilChanged()
.filter { $0 == 1 }
.subscribe(onNext: { value in expectation.fulfill() })
.disposed(by: self.disposeBag)
// When
reactor.action.onNext(.increase)
// Then
wait(for: [expectation], timeout: 3.0)
}
* 전체 소스 코드: https://github.com/JK0369/ExReactorKit/tree/BaseComponent
* 참고
- https://medium.com/styleshare/reactorkit-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-c7b52fbb131a
'Architecture (swift) > ReactorKit' 카테고리의 다른 글
[iOS - swift] 4. ReactorKit - `TaskEdit 구현`, 화면전환, 데이터 전달 (0) | 2021.12.03 |
---|---|
[iOS - swift] 3. ReactorKit - `TaskList 구현`, 템플릿 (template), 비동기 처리 transform(mutation:) (0) | 2021.12.02 |
[iOS - swift] 1. ReactorKit - 개념 (4) | 2021.11.30 |
Comments