Posts

Post not yet marked as solved
3 Replies
3.9k Views
In Unit Test, I have a simple table view with a bunch of basic cells (cells with just a label). I would like to access the cell using `cellForRow(at:)`, so I can test thing like selecting and deselecting the row programmatically, but this `cellForRow` queiry always returns `nil`.There is some discussion online that I should be using the data source's `tableView(_, cellForRowAt:)` instead. This is _not_ my intention. I only want to test the cell's visibility, test selecting and deselecting them. To test for visibility, `cellForRow(at:)` is the right function to use. Furthermore, the data source's `tableView(_, cellForRowAt:)` has no safeguard for out-of-range index access, while table view's `cellForRow(at:)` will gracefully return `nil` in this case, which I also wanted to test my table view controller on.However, while I can always get a valid cell from `tableViewController.tableView(_:cellForRowAt:)`, I couldn't understand why I always get `nil` from `tableView.cellForRow(at:)`. I have verfied both the `tableView` and the `tableViewController` are not `nil` in my unit test, and I have also triggered view loading with:_ = tableViewController.viewin `setUp()`. I also verified with `tableView.indexPathsForVisibleRows`, and the result _does_ include the index path I used for `cellForRow(at:)`.When I queried my cell through LLDB and breakpoints, sometimes my cell would show up properly. Is it possible that I am missing things like asynchronous waiting since loading up cells visually may be done in a different thread? Am I supposed to add expectation waiting of some sort to wait until the cells are fully loaded up before I can access them with `cellForRow(at:)`, even through `tableView.indexPathsForVisibleRows` already returns the expected index paths.? I tried to set this up but I'm not sure how to override my table view controller's `init()`.Here's my code in the Unit Test class.import XCTest @testable import TableViewTest class TableViewTestTests: XCTestCase { private var appDelegate: AppDelegate! private var tableVC: TableViewController! override func setUp() { super.setUp() appDelegate = UIApplication.shared.delegate as! AppDelegate let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main) tableVC = storyboard.instantiateViewController(withIdentifier: "TableViewController") as! TableViewController // Trigger view load and viewDidLoad() _ = tableVC.view } override func tearDown() { super.tearDown() } func testGetFirstRow() { let tableView = tableVC.tableView! let indexPath0 = IndexPath(item: 0, section: 0) let cell0 = tableView.cellForRow(at: indexPath0) let visibleRows = tableView.indexPathsForVisibleRows XCTAssert(visibleRows != nil) // PASSED XCTAssert(tableView.indexPathsForVisibleRows!.contains(indexPath0)) // PASSED XCTAssert(cell0 != nil) // FAILED } func testGetFirstRowDataSource() { let tableView = tableVC.tableView! let indexPath0 = IndexPath(item: 0, section: 0) // This won't check for cell visibility. let cell0 = tableVC.tableView(tableView, cellForRowAt: indexPath0) let visibleRows = tableView.indexPathsForVisibleRows XCTAssert(visibleRows != nil) // PASSED XCTAssert(tableView.indexPathsForVisibleRows!.contains(indexPath0)) // PASSED }
Posted
by huapapojt.
Last updated
.