Тестовая ячейка в UITableViewCell XCTest - PullRequest
0 голосов
/ 23 мая 2019

Я тестирую 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)}

Однако я получаю ячейку как ноль.

ЭтоУдивительно, поскольку точка останова в контроллере представления указывает, что ячейка выделяется, поэтому в строке

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

что-то не так. Так как же проверить содержимое этой ячейки?

1 Ответ

0 голосов
/ 23 июля 2019

Задача 1: Если вы определяете свою ячейку в кончике, вам нужно зарегистрировать этот кончик (вместо типа).

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)

Необходимость пройти через источник данных (и вспомогательную функцию, чтобы сделать его проще) описана в моей книге Модульное тестирование iOS на примере: советы и методики XCTest с использованием Swift

...