1

Je suis donc complètement novice en matière de test et j'avais juste besoin d'aide pour trouver par exemple comment j'écrirais un test pour chacun des trois cas dans l'énumération du modèle View (none, dontSeeProvider, showAllProviders).Comment est-ce que j'écrirais un test pour m'assurer que l'UIbutton "Montrer tous les fournisseurs" apparaît quand il y a plus de 12 articles ou plus dans la vue de tableau?

enum ProvidersButtonType { 
case none, dontSeeProvider, showAllProviders 
} 

Je n'ai pas été en mesure de comprendre comment écrire un test pour les cas « showAllProviders » et « dontSeeProviders ».

est la vue Modèle:

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) 
} 

} 

C'est le contrôleur de vue:

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) 
} 

} 

j'ai écrit un test pour le cas « none », mais n'ont pas été en mesure de comprendre les deux autres cas:

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) 
} 

Répondre

0

Je n'ai jamais utilisé FB Snapshot Tester. Je vais devoir regarder ça.

Voilà comment je le ferais:

Je n'exposer le ENUM au ViewController. setupRx() contiendrait ceci:

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  
} 

Ensuite, pour tester le titre du bouton, par exemple, je voudrais utiliser ces tests:

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. 
} 
+0

Merci beaucoup pour l'aide, vraiment apprécié !! Je ne peux pas changer le setupRx() atm): comment ferions-nous fonctionner les tests comme ça? – VeeArr

+0

Je dois également utiliser FBSnapshotTestCase au lieu de XCTest): – VeeArr

+0

Le point entier des tests d'écriture est de pouvoir * changer * le code testé. Cela dit, je ne peux pas vous aider concernant FBSnapshotTestCase. Je viens juste d'entendre parler de votre question. –