【问题标题】:Test Cell in a UITableViewCell XCTest在 UITableViewCell XCTest 中测试单元格
【发布时间】:2019-10-09 16:26:08
【问题描述】:

我正在测试视图控制器所在的 UITableView

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        setup()
    }

    func setup() {
        tableView.dataSource = self
        tableView.delegate = self
        tableView.register(CustomTableViewCell.self, forCellReuseIdentifier: "CustomTableViewCell")
    }


    var data = [1,2,3,4,5,6,7]
}

extension ViewController : UITableViewDelegate {

}

extension ViewController : UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath)
        cell.textLabel?.text = data[indexPath.row].description
        return cell
    }    
}

通过测试

func testViewCell() {
    guard let controller = controller else {
        return XCTFail("Could not instantiate ViewController")
    }

    let tableCell = Bundle(for: CustomTableViewCell.self).loadNibNamed("CustomTableViewCell", owner: nil)?.first as! CustomTableViewCell
    tableCell.textLabel?.text = "2"

    controller.loadViewIfNeeded()
    let actualCell = controller.tableView!.cellForRow(at: IndexPath(row: 0, section: 0) )

    XCTAssertEqual(actualCell, tableCell)}

但是我将单元格设为 nil。

这很令人惊讶,因为视图控制器中的断点表明单元正在被分配,所以该行有问题

let actualCell = controller.tableView!.cellForRow(at: IndexPath(row: 0, section: 0) )

那么我该如何测试这个单元格的内容呢?

【问题讨论】:

  • 你能不能让actualCell = controller.tableView!.cellForRow(at: IndexPath(row: 0, section: 0) ) as?改为 CustomTableViewCell。

标签: ios swift tdd xctest


【解决方案1】:

问题 1: 如果您在 nib 中定义单元格,则需要注册该 nib(而不是类型)。

tableView.register(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "CustomTableViewCell")

问题 2: 看来直接调用controller.tableView!.cellForRow(at:)可以返回nil。但这不是 UIKit 调用表格视图的方式。相反,通过其数据源调用它。让我们做同样的测试:

let actualCell = controller.tableView.dataSource?.tableView(controller.tableView, cellForRowAt: IndexPath(row: 0, section: 0))

这现在返回一个单元格,断言失败,说 CustomTableViewCell 的两个实例不相等。

奖励:如果您想将数据源移动到单独的类中,您可以在不更改测试的情况下这样做。测试不知道也不关心谁实现了数据源。

问题 3: 更改测试以将"1" 设置为预期单元格的文本标签仍然没有通过。这可能是因为每个单元格都有自己的layer。因此,与其设置预期的单元格,不如将实际的单元格转换为 CustomTableViewCell。然后你可以检查它的属性。

guard let cell = actualCell as? CustomTableViewCell else {
     XCTFail("Expected \(CustomTableViewCell.self), but was \(actualCell)")
     return
}
XCTAssertEqual(cell.textLabel?.text, "1")

改进: 遍历表视图的数据源,并将表视图作为第一个参数传递给它是很尴尬的。通过定义独立的辅助函数,我们可以更轻松地读写表视图测试。

func cellForRow(in tableView: UITableView, row: Int, section: Int = 0) -> UITableViewCell? {
    return tableView.dataSource?.tableView(tableView, cellForRowAt: IndexPath(row: row, section: section))
}

使用这个助手,我们可以简单地写:

let actualCell = cellForRow(in: controller.tableView row: 0)

【讨论】:

    【解决方案2】:

    第 1 步:转到 Storyboard 中视图控制器的 Identity Inspector 并为其指定一个故事板 ID。例如:“vcIdentifier”

    第 2 步:您已经在单元测试中获得了故事板的实例

    第 3 步:通过第 2 步中的情节提要实例实例化您的视图控制器

    第 4 步:从视图控制器获取对表格视图的访问权,并将其传递给测试中的“cellForRowAt”方法。请看下面的示例代码:

    let storyboard = UIStoryboard(name: "Main", bundle:nil)
    let newsViewController: UITableViewController = storyboard.instantiateViewController(identifier: "vcIdentifier")
    return newsViewController.tableView // Use this tableview to call 'cellforRow'
    

    第 5 步:删除在测试代码中添加的所有 tableview.register() 方法。如果你注册了cell方法,所有的outlet都会丢失。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-11
      • 2014-02-13
      • 2018-02-25
      • 1970-01-01
      • 2017-01-08
      • 2016-03-24
      • 1970-01-01
      相关资源
      最近更新 更多