Search code examples
swiftuitableviewcounttestcase

Get number rows in UITableView while unit tests- swift?


I'm writing a test case for UIViewController that has UITableView. I want to ask how can I get number of rows in UITableView

 func testloadingDataIntoUiTableView()
    {      
      var  countRow:Int =  viewController.formListTableView.numberOfRowsInSection   
      XCTAssert(countRow == 4)  
    }

Solution

  • Introduction

    Please keep in mind that the data model generates the UI. But you should not query the UI to retrieve your data model (unless we are talking about user input).

    Lets look at this example

    class Controller:UITableViewController {
    
        let animals = ["Tiger", "Leopard", "Snow Leopard", "Lion", "Mountain Lion"]
        let places = ["Maveriks", "Yosemite", "El Capitan"];
    
        override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
            return 2
        }
    
        override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            switch section {
            case 0: return animals.count
            case 1: return places.count
            default: fatalError()
            }
        }
    
        override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
            guard let cell = tableView.dequeueReusableCellWithIdentifier("MyCellID") else { fatalError("Who took the MyCellID cell???") }
            switch indexPath.section {
            case 0: cell.textLabel?.text = animals[indexPath.row]
            case 1: cell.textLabel?.text = places[indexPath.row]
            default: fatalError()
            }
            return cell
        }
    }
    

    The ugly solution

    In this case to get the total number of rows into the table we should query the model (the animals and places properties), so

    let controller: Controller = ...
    let rows = controller.animals.count + controller.places.count
    

    The nice solution

    Or even better we could make the animals and places properties private and add a computed property like this

    class Controller:UITableViewController {
    
        private let animals = ["Tiger", "Leopard", "Snow Leopard", "Lion", "Mountain Lion"]
        private let places = ["Maveriks", "Yosemite", "El Capitan"];
    
        var totalNumberOfRows: Int { return animals.count + places.count }
    
        ...
    

    Now you can use this

    let controller: Controller = ...
    let rows = controller.totalNumberOfRows