Модульный тест, когда 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 ответа

Несколько вариантов, чтобы попробовать:

  1. Swizzle UIViewController's present(_, animated, completion) чтобы захватить то, что было представлено. Я делаю это для UIAlertControllers https://qualitycoding.org/testing-uialertcontroller/ но это потому, что UIAlertControllers очень распространены. Это может не стоить хлопот для вашего пользовательского окна.
  2. Не уверен, что это сработает. makeKeyAndVisible а также present вероятно, не дают немедленных результатов. Вместо этого они планируют работу. Таким образом, вы можете попробовать накачать цикл запуска с RunLoop.current.run(until: Date()), Это работает для активации текстовых полей, но я не знаю, будет ли это работать для вас.
  3. Аналогичным образом попробуйте добавить XCTestExpectation и waitForExpectations с небольшим таймаутом. Как я отмечаю в https://qualitycoding.org/asynchronous-tests/, не делайте никаких утверждений в вашем обработчике ожидания. Вместо этого соберите информацию, которую вы хотите и fulfill ожидание. Тогда утверждай против того, что ты захватил.
  4. Измените код, который вы написали, чтобы облегчить тестирование. Замените последнюю строку, вызвав блок, сохраненный в свойстве в SUT. Для тестирования замените этот блок. Тестовый блок может вызывать обработчик завершения, который дает вам возможность протестировать обработчики.
  5. Протестируйте этот код вручную в соответствии с вашими требованиями. Затем поиграйте с ним, чтобы ваши тесты проверяли, что этот метод вызывается (но на самом деле его не вызывают).

Код модульного тестирования, имеющий побочные эффекты, может быть невероятно сложным, особенно если побочные эффекты связаны с аппаратным обеспечением, таким как экран устройства. По этой причине компоненты пользовательского интерфейса не подходят для модульного тестирования, поскольку они обычно включают операции с графическим процессором.

Теперь, если вы действительно хотите протестировать компонент, вы можете пойти по двум маршрутам:

  • вы пишете тесты снимков
  • Вы извлекаете всю бизнес-логику в отдельные классы и тестируете их.

Вывод: модульное тестирование бизнес-кода, и пусть QA-тестирование пользовательского интерфейса ведет себя как ожидалось.

Другие вопросы по тегам