NimbleRxTest 1.0.0

NimbleRxTest 1.0.0

Balázs Hajagos 维护。



 
依赖项
Nimble>= 0
Quick>= 0
RxSwift>= 0
RxTest>= 0
 

  • Balázs Hajagos

Nimble RxTests

这个小巧的辅助库有助于连接 Swift 中最受欢迎的测试库之一(Quick)和响应式世界。第一次当我不得不为响应式项目编写测试时,我一直在使用 RxBlocking 或解包事件,通常使用 .debug() 来帮助理解在响应式链中发生了什么。过了一会儿,我想“噢,好吧!我有这个可爱的小 Nimble,我知道 XCAssert 辅助工具是为 RxTest 创建的,为什么不也在 Nimble 中做同样的呢?”在我意识到之前,我使用相同的代码帮助我在 3 或 4 个项目中将 Nimble 和 Rx 绑定在一起,并在其中每一个项目中复制相同的文件。

于是 NimbleRxTest 库应运而生。

用例

如果您正在使用 Nimble 并且 QuickNimble,那么您可能遇到过类似这样的问题

// Swift

import Quick
import Nimble
import RxSwift
import RxTest

protocol Alive {}
    
struct Fish: Alive {}
struct Shark: Alive {}
struct Boat {}
    
final class Dolphin {
    var soundEmissions: Observable<String> {
        return encounter.flatMapLatest { thing -> Observable<String> in
            switch thing {
            case is Fish:
                return .just("click")
            case is Alive:
                return .just("whistle")
            default:
                return .empty()
            }
        }
    }
    
    var encounter = PublishSubject<Any>()
}

final class FactionSelectionViewModelTests: QuickSpec {
    override func spec() {
        
        describe("a reactive 🐬") {
            var dolphin: Dolphin!
            var testScheduler: TestScheduler!
            var disposeBag: DisposeBag!
            
            beforeEach {
                dolphin = Dolphin()
                testScheduler = TestScheduler(initialClock: 0)
                disposeBag = DisposeBag()
            }
            
            describe("encountering") {
                var encounters: [Recorded<Event<Any>>]!
                
                context("with a series of things") {
                    beforeEach {
                        encounters = [
                            .next(100, Boat()),
                            .next(200, Fish()),
                            .next(300, Fish()),
                            .next(400, Shark()),
                            .next(500, Boat()),
                            .completed(600)
                        ]
                    }
                    
                    it("emits sounds accordingly") {
                        let observer = testScheduler.createObserver(String.self)
                        
                        testScheduler
                            .createHotObservable(encounters)
                            .bind(to: dolphin.encounter)
                            .disposed(by: disposeBag)
                        
                        dolphin
                            .soundEmissions
                            .bind(to: observer)
                            .disposed(by: disposeBag)
                        
                        // Yeah let's just expect these sounds
                        let expected = ["click", "click", "whistle"]
                        
                        testScheduler.start()
                        
                        // Uhh, let's just assume checking the returned strings is enough.
                        // Also just hide those pesky nils. (If you are vigilant enough you 
                        // see that the below compact map is intended to filter out one extra 
                        // nil emission from the .completed event.)
                        expect(observer.events.compactMap { $0.value.element }).to(equal(expected))
                    }
                }
            }
        }
	}
}

相反,如果我们为 Nimble 编写合适的匹配器,我们可以这样写

// Same as above

                    it("emits sounds accordingly") {
                        let observer = testScheduler.createObserver(String.self)
                        
                        testScheduler
                            .createHotObservable(encounters)
                            .bind(to: dolphin.encounter)
                            .disposed(by: disposeBag)
                        
                        dolphin
                            .soundEmissions
                            .bind(to: observer)
                            .disposed(by: disposeBag)
                        
                        let expected: [Recorded<Event<String>>] = [
                            .next(200, "click"),
                            .next(300, "click"),
                            .next(400, "whistle"),
                            .completed(600)
                        ]
                        
                        testScheduler.start()
                        
                        expect(observer.events).to(equal(expected))
                    }
                    
// Same as above

这不是很美吗?它解决了忽略事件和时间的问题,并且使我们免于映射苦难,结果产生更干净、更复杂的测试。

要求

  • XCode 10.0
  • Swift 4.2

安装

CocoaPods

使用pod --version测试: 1.6.1

# Podfile
use_frameworks!

target 'YOUR_TARGET_NAME' do
    pod 'NimbleRxTest',    '~> 1.0.0'
end

替换YOUR_TARGET_NAME,然后在Podfile目录中,输入

$ pod install