我如何编写测试以确保UI按钮"显示所有提供商"当表格视图中有超过12个或更多项目时会出现?

时间:2017-05-16 19:21:02

标签: swift viewmodel viewcontroller rx-swift fbsnapshottestcase

所以我对测试完全陌生,我只是需要一些帮助,例如我如何为View Model的枚举中的每个案例编写一个测试(none,dontSeeProvider,showAllProviders)。

enum ProvidersButtonType {
case none, dontSeeProvider, showAllProviders
}

我还没有能够弄清楚如何为病例编写测试" showAllProviders"和" dontSeeProviders"。

这是视图模型:

import RxSwift
import RxCocoa

struct TopProvidersPickerItem {
let provider: MVPD

let logoImage: Observable<UIImage>

init(provider: MVPD, imageLoader: DecodableProviding) {
    self.init(provider: provider, logoImage: imageLoader.image(fromURL: provider.logoUrl))
}

init(provider: MVPD, logoImage: Observable<UIImage>) {
    self.provider = provider
    self.logoImage = logoImage.catchErrorJustReturn(UIImage())
}
}

enum ProvidersButtonType {
case none, dontSeeProvider, showAllProviders
}

struct TopProvidersPickerViewModel {
var caption: String {
    return "Get access to more full episodes by signing in with your TV Provider"
}

let buttonType = Variable<ProvidersButtonType>(.none)
let items: Observable<[TopProvidersPickerItem]>
let selectedItem: PublishSubject<TopProvidersPickerItem> = PublishSubject()
let showAllProvidersTrigger: PublishSubject<Void> = PublishSubject()
let mvpdPicked: Observable<MVPD>

init(topProviders: Observable<[MVPD]>, imageLoader: DecodableProviding) {
    let items = topProviders.map({ mvpds in
        return mvpds.map { mvpd in
            TopProvidersPickerItem(provider: mvpd, imageLoader: imageLoader)
        }
    })
    self.init(items: items)
}

init(items: Observable<[TopProvidersPickerItem]>) {
    self.items = items
    mvpdPicked = selectedItem.map { $0.provider }
    let buttonType = items.map { (array) -> ProvidersButtonType in
        if array.count > 12 {
            return .showAllProviders
        } else {
            return .dontSeeProvider
        }
    }
    buttonType.bind(to: self.buttonType)
}

}

这是视图控制器:

import UIKit
import RxCocoa
import RxSwift

public class ProviderCollectionViewCell: UICollectionViewCell {
    @IBOutlet public private(set) weak var imageView: UIImageView!
}

public class TopProvidersPickerViewController: UIViewController, 
ViewModelHolder {
var viewModel: TopProvidersPickerViewModel! = nil
private let bag = DisposeBag()

@IBOutlet public private(set) weak var collectionView: UICollectionView!
@IBOutlet public private(set) weak var captionLabel: UILabel!
@IBOutlet weak var viewAllProvidersButton: UIButton!

override public func viewDidLoad() {
    super.viewDidLoad()
    captionLabel.text = viewModel.caption
    setupRx()
}

private func setupRx() {
    viewModel.buttonType.asObservable().subscribe(onNext: { [button = self.viewAllProvidersButton] type in
        button?.isHidden = false

        switch type {
        case .none:
            button?.isHidden = true
        case .dontSeeProvider:
            button?.setTitle("Don't see provider", for: .normal)
        case .showAllProviders:
            button?.setTitle("Show all providers", for: .normal)
        }
        })
        .disposed(by: bag)

    viewModel.items
        .bind(to: collectionView
        .rx
        .items(cellIdentifier: "ProviderCell", cellType: ProviderCollectionViewCell.self)) { [ unowned self ] _, item, cell in
            item.logoImage.bind(to: cell.imageView.rx.image).addDisposableTo(self.bag)
        }
        .addDisposableTo(bag)

    collectionView
        .rx
        .modelSelected(TopProvidersPickerItem.self)
        .bind(to: self.viewModel.selectedItem)
        .addDisposableTo(bag)

    viewAllProvidersButton
        .rx
        .tap
        .bind(to: self.viewModel.showAllProvidersTrigger)
        .addDisposableTo(bag)
}

}

我为&#34; none&#34;写了一个测试。案件,但是还没有能够找出其他两个案例:

import FBSnapshotTestCase
import OHHTTPStubs
import RxSwift
@testable import AuthSuite

class TopProvidersPickerViewControllerTests: FBSnapshotTestCase, 
ProvidersViewControllerTests {

override func setUp() {
    super.setUp()
    recordMode = true
}

func testDoesNotShowButtonWhenLoadingProviders() {
    let viewModel = TopProvidersPickerViewModel(items: .never())
    let controller = TopProvidersPickerViewController.instantiateViewController(with: viewModel)
    presentViewController(controller)

    FBSnapshotVerifyView(controller.view)
}

1 个答案:

答案 0 :(得分:0)

我从未使用过FB Snapshot Tester。我将不得不调查一下。

这是我将如何做到的:

我不会将枚举暴露给ViewController。 setupRx()将包含此代码:

private func setupRx() {

    viewModel.buttonTitle
        .bind(to: viewAllProvidersButton.rx.title(for: .normal))
        .disposed(by: bag)

    viewModel.buttonHidden
        .bind(to: viewAllProvidersButton.rx.isHidden)
        .disposed(by: bag)

    // everything else      
}

然后测试按钮的标题,例如,我会使用这些测试:

import XCTest
import RxSwift
@testable import RxPlayground

class TopProvidersPickerViewModelTests: XCTestCase {

    func testButtonTitleEmptyItems() {
        let topProviders = Observable<[MVPD]>.just([])
        let decodableProviding = MockDecodableProviding()

        let viewModel = TopProvidersPickerViewModel(topProviders: topProviders, imageLoader: decodableProviding)

        var title: String = ""
        _ = viewModel.buttonTitle.subscribe(onNext: { title = $0 })

        XCTAssertEqual(title, "Don't see provider")
    }

    func testButtonTitle12Items() {
        let topProviders = Observable<[MVPD]>.just(Array(repeating: MVPD(), count: 12))
        let decodableProviding = MockDecodableProviding()

        let viewModel = TopProvidersPickerViewModel(topProviders: topProviders, imageLoader: decodableProviding)

        var title: String = ""
        _ = viewModel.buttonTitle.subscribe(onNext: { title = $0 })

        XCTAssertEqual(title, "Don't see provider")
    }

    func testButtonTitle13Items() {
        let topProviders = Observable<[MVPD]>.just(Array(repeating: MVPD(), count: 13))
        let decodableProviding = MockDecodableProviding()

        let viewModel = TopProvidersPickerViewModel(topProviders: topProviders, imageLoader: decodableProviding)

        var title: String = ""
        _ = viewModel.buttonTitle.subscribe(onNext: { title = $0 })

        XCTAssertEqual(title, "Show all providers")
    }
}


class MockDecodableProviding: DecodableProviding {
    // nothing needed for these tests.
}