Обновлено: Длинные s Короче, нет отличного способа сделать это. Что затрудняет то, что, хотя большинство элементов управления, которые мы использовали для тестирования, имеют действие и отправителя, прикосновение к UITableViewCell является другой парадигмой.
Тем не менее, наличие идентификатора segue в основном является предварительным условием для любой стратегии.
Один из способов получить ссылку на ячейку и вызовите performSegue(withIdentifier:,sender:)
:
class ViewControllerTests: XCTestCase {
func testClickingACell() {
let controller = UIStoryboard(name: "ViewController", bundle: nil).instantiateInitialViewController() as! ViewController
let cell = controller.tableView.dataSource?.tableView(controller.tableView, cellForRowAt: IndexPath(row: 0, section: 0))
controller.performSegue(withIdentifier: "MySegue", sender: cell)
XCTAssertNotNil(controller.presentedViewController as? TheDestinationViewController)
}
}
Другим (полностью избыточен) способом будет иметь пользовательские ячейки, где вы справиться со всеми вашей собственной сенсорной логикой. Это было бы безумным, но это была возможность, и он открыл бы больше возможностей для тестирования. Я не собираюсь показывать этот путь, потому что это был бы безумный способ сделать это.
Другой способ - использовать другую архитектуру, которая избавляется от UIKit
и позволяет тестировать только логику performSegue
. Пример:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet var myTableView: UITableView!
var navigator: UIViewController?
override func viewDidLoad() {
super.viewDidLoad()
navigator = self
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
navigator?.performSegue(withIdentifier: "MySegue", sender: nil)
}
}
Это позволяет сделать что-то вроде этого в тестах:
class MockNavigator: ViewController {
var performSegueCalled = false
var performSegueIdentifier: String?
override func performSegue(withIdentifier identifier: String, sender: Any?) {
performSegueCalled = true
performSegueIdentifier = identifier
}
}
func testExample() {
let controller = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController() as! ViewController
controller.loadViewIfNeeded()
// Need to keep a reference to be able to assert against it
let mockNavigator = MockNavigator()
controller.navigator = mockNavigator
controller.tableView(controller.myTableView, didSelectRowAt: IndexPath(row: 0, section: 0))
XCTAssertTrue(mockNavigator.performSegueCalled)
XCTAssertEqual(mockNavigator.performSegueIdentifier, "MySegue")
}
Другой способ структурирования кода, чтобы избежать UIKit использовать что-то вроде шаблона вид модели-координатор для создания и протестируйте viewModel.В основном вы бы сказали своему координатору, что ячейка выбрана, и координатор обновит модель представления с желаемым идентификатором сегмента. Таким образом, вы можете протестировать объект координатора и быть в основном уверены, что вы активируете правильное segue, если координатор подключен. Простой ручной тест скажет вам об этом.
В псевдокоде:
struct ViewModel {
let labelText: String
let segueIdentifier: String
}
class Coordinator {
var data = [YourObject]()
var viewModel = ViewModel(labelText: "", segueIdentifier: "")
func selectedItem(at row: Int) {
let item = data[row]
// Do some logic to figure out which identifier you want
var segueIdentifer: String
if item == whatever {
segueIdentifier = "something"
}
viewModel = ViewModel(labelText: item.text, segueIdentifier: segueIdentifier)
}
}
Наверное, лучший способ это сочетание подходов. Используйте координатор с моделью просмотра, которая проверена сама по себе. Затем выполните тест, в котором вы используете UIKit для выбора ячейки и убедитесь, что издеваемое выполнение этого координатора используется, как ожидалось. Чем меньше единиц вы тестируете, тем легче будет.
эй, ваш вопрос непонятен! почему вы хотите проверить, что segue запускается командой didSelectRow? Это очевидно, поскольку в этом VC только один раз. Итак, ваш вопрос, чтобы определить, какие триггеры tableviewcell готовят к настройке? –
@JenJose это надуманный пример, у реального проекта есть еще много ячеек, пользовательских ячеек и т. Д. –
У меня такая же проблема, вы нашли решение? –