我有一个包含tableView的ViewController。由于我需要保持代码完全覆盖测试,我需要为[tableView:cellForRowAtIndexPath]编写测试
import UIKit
class MainViewController: UIViewController, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
var source = [
Country(name: "USA", capital: "Washington, D.C."),
Country(name: "Argentina", capital: "Buenos Aires"),
Country(name: "Mexico", capital: "Mexico, D.F.")
]
let cellIdentifier = NSStringFromClass(MainViewController.self)
init() {
super.init(nibName: "MainViewController", bundle: nil)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
let nib = UINib(nibName: "CustomCell", bundle: nil)
tableView?.registerNib(nib, forCellReuseIdentifier: cellIdentifier)
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return source.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? CustomCell
if let cell = cell {
cell.countryLabel.text = source[indexPath.row].name
cell.capitalLabel.text = source[indexPath.row].capital
return cell
}
return CustomCell()
}
}
struct Country {
var name: String
var capital: String
}
测试如下所示:
import UIKit
import XCTest
class MainViewControllerTests: XCTestCase {
var controller: MainViewController!
override func setUp() {
super.setUp()
controller = MainViewController()
controller.view.description
}
override func tearDown() {
super.tearDown()
}
func testTableViewOutlet() {
XCTAssertNotNil(controller.tableView)
}
func testTableViewCellForRowAtIndexPath() {
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
let cell = controller.tableView(controller.tableView, cellForRowAtIndexPath: indexPath) as! CustomCell
XCTAssertEqual(cell.countryLabel.text!, "USA")
XCTAssertEqual(cell.capitalLabel.text!, "Washington, D.C.")
}
}
运行测试时出现以下错误:
Test Case '-[CustomTableViewCellTests.MainViewControllerTests testTableViewCellForRowAtIndexPath]' started.
fatal error: unexpectedly found nil while unwrapping an Optional value
由于[dequeueReusableCellWithIithntifier]仅在从测试运行时返回nil,因此此函数在我的生产应用程序中提到了几个月的测试。我实际上尝试了很多我在StackOverflow中读过的方法,例如:
底线是我接近解决方案,我创建了一个CustomCell对象,但是单元格的出口仍为零。我还没有找到能够实现初始化元素出口的代码片段,因此我可以通过测试。
我包含一个基本的iOS项目,它有自己的git,其中包含我在此处包含的代码。它是一个UIViewController,包含UITableView,它使用自定义UITableViewCell显示数据。我希望找到一个解决方案,通过其出口实现自定义单元以使测试通过。
Git回购来源: https://bitbucket.org/jallauca/customcell/src
克隆git repo:
git clone https://bitbucket.org/jallauca/customcell.git
答案 0 :(得分:3)
对我来说,(Swift 3)我不得不调用cellForRow数据源cellForRowAt函数而不是直接从tableView.cellForRow函数访问
//this
let cell = controller.tableView(controller.tableView, cellForRowAt: IndexPath(row: 0, section: 0))
//instead of this
let cell = controller.tableView.cellForRow(at: IndexPath(row: 0, section: 0))
答案 1 :(得分:0)
这里有很多可能出错的事情。一些可能性:
tableView
本身可能是零。tableView:cellForRowAtIndexPath:
方法中分配新单元格。如果没有可用于重用的单元,那么过去是必要的,但是现在正确配置的表将根据需要实例化新单元,而IIRC实例化自己的单元可能会导致崩溃。答案 2 :(得分:0)
有两个单独的概念,tableView和dataSource。 TableView只是一个视图,并且具有作为视图的单元格。 DataSource是tableView的数据提供程序,并且是唯一负责数据的组件。
在测试示例中,您调用tableView.cellForRowAtIndexPath
函数以获取特定indexPath中的单元格。根据官方文档, 如果该单元格不可见,此函数将返回nil 。因此,仅当您知道表格可见时,才应使用此功能。
在您的示例中,您试图测试您的表将正确加载数据。引用数据时,首先要想到的是数据源。因此,您需要测试dataSource将正确的信息绑定到您的单元格。结果,您致电controller.tableView.dataSource(controller.tableView, cellForRowAt: IndexPath(row: 0, section: 0)))
答案 3 :(得分:0)
步骤1:在情节提要中转到视图控制器的Identity Inspector,并为其指定一个情节提要ID。例如:“ vcIdentifier”
第2步:您已经在单元测试中获得了情节提要的实例
第2步:通过第2步中的情节提要实例实例化视图控制器
第3步:从viewcontroller中访问表视图,然后将其传递给测试中的'cellForRowAt'方法。请参见下面的示例代码:
let storyboard = UIStoryboard(name: "Main", bundle:nil)
let newsViewController: UITableViewController = storyboard.instantiateViewController(identifier: "vcIdentifier")
return newsViewController.tableView