#swift #tdd #xctest #xcode12 #xcuitest
Вопрос:
Я пытаюсь создать UITestCase для UIViewControllers, но когда я загружаю основную раскадровку в свою QuizAppUITests
, она не может быть идентифицирована, Bundle
и это приводит к ошибке ниже
Не удалось найти раскадровку с именем «Main» в пакете NSBundle </Users/mac/Library/Developer/CoreSimulator/Devices/CC199C69-F398-4A7C-882E-BFD3E72B95D3/data/Containers/Bundle/Application/BCC3F88D-E08C-4491-8340-699EAF98AB28/QuizAppUITests-Runner.app> (загружено) (исключение NSInvalidArgumentException)
Я также добавил основную раскадровку в цель QuizAppUITests, и ниже приведен мой код для тестирования
import XCTest
@testable import QuizApp
class QuizViewControllerUITests: XCTestCase {
func makeSUT() -> QuizViewController {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for: type(of: self)))
let sut = storyboard.instantiateViewController(withIdentifier: "QuizViewController") as! QuizViewController
_ = sut.view
return sut
}
func test_loadQuizViewController() {
let sut = makeSUT()
sut.headerQuestion = "Q1"
XCTAssertEqual(sut.headerQuestion, "Q1")
}
}
Требуется ли что-либо изменить в настройке QuizAppUITests
цели?
Комментарии:
1. Что ты пытаешься сделать? Я не знаю, почему вы используете раскадровку для UITest. Есть и другие, более эффективные способы тестирования UIT в iOS.
2. Согласен, это очень странный способ использования XCUITest. Это похоже на модульный тест пользовательского интерфейса.
3. @Kudos Я хочу проверить, существует ли instantiateViewController из раскадровки и раскадровки в комплекте или нет.
Ответ №1:
Все это не имеет смысла для теста пользовательского интерфейса. Вместо этого поместите свой код в цель модульного тестирования, которая такова QuizAppTests
.
В моей книге Модульное тестирование iOS на примере есть глава под названием «Контроллеры просмотра нагрузки». Посмотрите, что там говорится о контроллерах просмотра на основе раскадровки:
- Не включайте раскадровку в свою тестовую цель. Поместите его только в цель вашего приложения.
- Затем вы можете загрузить раскадровку с
UIStoryboard(name: "Main", bundle: nil)
- Существует новый способ создания экземпляра контроллера представления, который не требует принудительного приведения. Вместо
instantiateViewController(withIdentifier:)
этого используйтеinstantiateViewController(identifier:)
и назначьте его явно типизированной переменной.
Подобный этому:
let sut: QuizViewController = storyboard.instantiateViewController(
identifier: "QuizViewController"
)
Поскольку вы используете имя класса в качестве идентификатора, мы даже можем избавиться от строки. Это защищает нас от опечаток во время компиляции:
let sut: QuizViewController = storyboard.instantiateViewController(
identifier: String(describing: QuizViewController.self)
)
Наконец, вместо _ = sut.view
этого мы можем более подробно рассказать о загрузке представления:
sut.loadViewIfNeeded()
Это подключает розетки.
Опять же, все это относится к вашей цели модульного тестирования QuizAppTests
, а не к вашей цели тестирования пользовательского QuizAppUITests
интерфейса .
Для ваших реальных тестов не просто назначайте свойство в тестируемой системе и проверяйте, было ли оно назначено. Это ничего не доказывает. Вместо этого я бы сосредоточился на тестировании:
- Что выходы не равны нулю
- Это взаимодействие с элементами управления делает то, что вы хотите
- Что навигация работает
- Внешний вид этого представления не изменился по сравнению с утвержденным снимком
Все это можно сделать с помощью TDD.