class RemoveMyDataConsentFormVCTests: XCTestCase {
var viewController: RemoveMyDataConsentFormVC!
override func setUp() {
super.setUp()
let storyboard = UIStoryboard(name: "RemoveMyDataConsentForm", bundle: nil) // Replace "Main" with your storyboard name
viewController = storyboard.instantiateViewController(withIdentifier: "RemoveMyDataConsentFormVC") as? RemoveMyDataConsentFormVC
viewController.loadViewIfNeeded()
}
override func tearDown() {
viewController = nil
super.tearDown()
}
func testSetupTextFields() {
if viewController.emailTextField.text == "" {
viewController.emailTextField.text = nil
}
XCTAssertNotNil(viewController.emailTextField.text, "Error for email should be hidden")
XCTAssertTrue((viewController.errorForStates != nil), "Error for email should be hidden")
XCTAssertTrue((viewController.errorForCountries != nil), "Error for email should be hidden")
XCTAssertTrue((viewController.errorForLastName != nil), "Error for email should be hidden")
XCTAssertTrue((viewController.errorForFirstName != nil), "Error for email should be hidden")
}
}
Выше приведен код моего UIViewController
, для которого я написал модульный тест для настройки текстовых полей. Я ищу пример, позволяющий улучшить способ написания модульных тестов с использованием Swift 5.
Тест проходит, но писать модульный тест правильно, похоже, не рекомендуется.
Существует два распространенных типа тестов:
Мы тестируем поведение пользовательского интерфейса (например, UIViewController
подклассы) в UI-тестах. Но когда мы пишем эти тесты, мы обычно не проверяем внутреннее состояние контроллера представления, а скорее проверяем то, что представлено в пользовательском интерфейсе.
Например, тест пользовательского интерфейса предоставит некоторое значение некоторому элементу управления пользовательского интерфейса (например, текстовому полю), а затем тест пользовательского интерфейса проверит, правильно ли пользовательский интерфейс отразил ошибку. Но мы тестируем не внутренние объекты ошибок, а то, как они были представлены в пользовательском интерфейсе.
Мы используем модульные тесты для проверки поведения отдельных методов, а не пользовательских интерфейсов. Итак, мы могли бы написать модульные тесты, которые проверят, что данная функция вернула ожидаемый результат.
Например, можно проверить, что некоторая текстовая строка, предоставленная какой-либо функции «проверки строки», вернула правильный объект ошибки.
С этой целью многие из нас пытаются абстрагировать бизнес-логику от уровня представления (т. е. мы вытаскиваем ее из контроллера представления, например). Разные команды/проекты используют для этого разные методы/терминологию: некоторые используют «модели представления». Некоторые используют «презентационные» объекты. Некоторые используют более абстрактный «контроллер» (не путать с «контроллером представления», специфичным для пользовательского интерфейса) или «сервисные» объекты для инкапсуляции этой бизнес-логики.
Независимо от того, как к этому подойти, идея состоит в том, что по соображениям тестируемости (а также просто для общего хорошего дизайна) мы абстрагируем бизнес-логику от уровня пользовательского интерфейса нашей кодовой базы (т. Е. Мы извлекаем ее из контроллеров представления). Затем мы пишем «модульные тесты» для проверки этих функций/объектов бизнес-логики, полностью отделенных от любого кода пользовательского интерфейса. Затем мы пишем «тесты пользовательского интерфейса», чтобы убедиться, что наш пользовательский интерфейс ведет себя так, как мы ожидали, а не для проверки внутреннего состояния уровня представления.
Посмотрите разницу между модульными тестами и тестами пользовательского интерфейса примерно за 1:33 до WWDC 2023 Исправляйте сбои быстрее с помощью отчетов о тестировании Xcode: