Модульный тест, когда rootViewController представляет представление?
Я пытаюсь выполнить модульное тестирование функции, которая представляет представление вне viewController:
public func presentInOwnWindow(animated: Bool, completion: (() -> Void)?) {
let alertWindow = UIWindow(frame: UIScreen.main.bounds)
alertWindow.rootViewController = UIViewController()
alertWindow.windowLevel = UIWindowLevelAlert + 1;
alertWindow.makeKeyAndVisible()
alertWindow.rootViewController?.present(self, animated: animated, completion: completion)
}
пока все, что я могу думать о том, как провести юнит-тестирование, так:
func test_presentInOwnWindow () {
let presented = sut.presentInOwnWindow(animated: true) {}
XCTAssertNotNil(presented)
}
Я попытался передать bool для блока завершения:
завершение: ((Bool) -> Void)
но так как он вызывает завершение для:
RootViewController?.present
Я получаю ошибку:
Не удается преобразовать значение типа '((Bool) -> Void)?' к ожидаемому типу аргумента '(() -> Void)?'
Есть идеи, как правильно протестировать функцию?
2 ответа
Несколько вариантов, чтобы попробовать:
- Swizzle UIViewController's
present(_, animated, completion)
чтобы захватить то, что было представлено. Я делаю это для UIAlertControllers https://qualitycoding.org/testing-uialertcontroller/ но это потому, что UIAlertControllers очень распространены. Это может не стоить хлопот для вашего пользовательского окна. - Не уверен, что это сработает.
makeKeyAndVisible
а такжеpresent
вероятно, не дают немедленных результатов. Вместо этого они планируют работу. Таким образом, вы можете попробовать накачать цикл запуска сRunLoop.current.run(until: Date())
, Это работает для активации текстовых полей, но я не знаю, будет ли это работать для вас. - Аналогичным образом попробуйте добавить XCTestExpectation и
waitForExpectations
с небольшим таймаутом. Как я отмечаю в https://qualitycoding.org/asynchronous-tests/, не делайте никаких утверждений в вашем обработчике ожидания. Вместо этого соберите информацию, которую вы хотите иfulfill
ожидание. Тогда утверждай против того, что ты захватил. - Измените код, который вы написали, чтобы облегчить тестирование. Замените последнюю строку, вызвав блок, сохраненный в свойстве в SUT. Для тестирования замените этот блок. Тестовый блок может вызывать обработчик завершения, который дает вам возможность протестировать обработчики.
- Протестируйте этот код вручную в соответствии с вашими требованиями. Затем поиграйте с ним, чтобы ваши тесты проверяли, что этот метод вызывается (но на самом деле его не вызывают).
Код модульного тестирования, имеющий побочные эффекты, может быть невероятно сложным, особенно если побочные эффекты связаны с аппаратным обеспечением, таким как экран устройства. По этой причине компоненты пользовательского интерфейса не подходят для модульного тестирования, поскольку они обычно включают операции с графическим процессором.
Теперь, если вы действительно хотите протестировать компонент, вы можете пойти по двум маршрутам:
- вы пишете тесты снимков
- Вы извлекаете всю бизнес-логику в отдельные классы и тестируете их.
Вывод: модульное тестирование бизнес-кода, и пусть QA-тестирование пользовательского интерфейса ведет себя как ожидалось.