Не удалось загрузить основную.Раскадровка в XCUITest

#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.