Невозможно запустить пользовательский UIViewController из UIStoryboard в XCTest

158
12

В Swift, Xcode6-Beta5, я пытаюсь unit test мой "ViewController", а не очень творческое имя.


От взгляда на другие ответы, я думаю, что у меня не настроено целевое задание "Тесты".


Ошибка кода проверки:


  func testItShouldLoadFromStoryboard() {

var storyBoard: UIStoryboard?
var anyVC: AnyObject?
var viewController: ViewController?
var uiViewController: UIViewController?

storyBoard = UIStoryboard(name:"Main", bundle: nil)
XCTAssert(storyBoard != nil, "Test Not Configured Properly")

anyVC = storyBoard?.instantiateInitialViewController()
viewController = anyVC as? ViewController
// Failing Assertion
XCTAssert(viewController != nil, "Test Not Configured Properly")

uiViewController = anyVC as? UIViewController
XCTAssert(uiViewController != nil, "Test Not Configured Properly")

}


Я могу заставить трансляцию со следующими строками:


anyVC = storyBoard?.instantiateInitialViewController()
viewController = (anyVC != nil) ? (anyVC as ViewController) : nil

Но это вызвало следующий сбой:


libswiftCore.dylib`swift_dynamicCastClassUnconditional:
0x10724f5a0: pushq %rbp
0x10724f5a1: movq %rsp, %rbp
0x10724f5a4: pushq %r14
0x10724f5a6: pushq %rbx
0x10724f5a7: movq %rsi, %rbx
0x10724f5aa: movq %rdi, %r14
0x10724f5ad: testq %r14, %r14
0x10724f5b0: je 0x10724f5de ; swift_dynamicCastClassUnconditional + 62
0x10724f5b2: movabsq $-0x7fffffffffffffff, %rax
0x10724f5bc: andq %r14, %rax
0x10724f5bf: jne 0x10724f5de ; swift_dynamicCastClassUnconditional + 62
0x10724f5c1: movq %r14, %rdi
0x10724f5c4: callq 0x107279a6e ; symbol stub for: object_getClass
0x10724f5c9: nopl (%rax)
0x10724f5d0: cmpq %rbx, %rax
0x10724f5d3: je 0x10724f5ed ; swift_dynamicCastClassUnconditional + 77
0x10724f5d5: movq 0x8(%rax), %rax
0x10724f5d9: testq %rax, %rax
0x10724f5dc: jne 0x10724f5d0 ; swift_dynamicCastClassUnconditional + 48
0x10724f5de: leaq 0x3364d(%rip), %rax ; "Swift dynamic cast failed"
0x10724f5e5: movq %rax, 0xa456c(%rip) ; gCRAnnotations + 8
0x10724f5ec: int3
0x10724f5ed: movq %r14, %rax
0x10724f5f0: popq %rbx
0x10724f5f1: popq %r14
0x10724f5f3: popq %rbp
0x10724f5f4: retq
0x10724f5f5: nopw %cs:(%rax,%rax)

Я также успешно создал экземпляр ViewController напрямую, но не выполняет обработку IBOutlet, которая является одной из целей моих тестов, чтобы я не нарушил связь, переименовав вещи, удалив соединения в Редактор раскадровки или многие другие способы, которые я нашел, чтобы сломать вещи...


РЕДАКТИРОВАТЬ ----
Я начал с нового проекта, выбрал приложение IOS Application → Single View Application.


Заменил testExample кодом, как показано ниже, добавлен ViewController в тестовый объект. Аналогичные результаты. Этот шаблон имеет единый контроллер вида типа ViewController, больше ничего в раскадровке.


  func testExample() {

var storyBoard: UIStoryboard?
var anyVC: AnyObject?
var viewController: ViewController?

storyBoard = UIStoryboard(name:"Main", bundle: nil)
XCTAssert(storyBoard != nil, "Test Not Configured Properly")

anyVC = storyBoard?.instantiateInitialViewController()
viewController = anyVC as? ViewController
XCTAssert(viewController != nil, "Test Not Configured Properly")

// This is an example of a functional test case.
XCTAssert(true, "Pass")

}


Следующий вывод lldb в точке останова сразу после значения anyVC:


(lldb) po anyVC
(instance_type = Builtin.RawPointer = 0x00007fe22c92a290 -> 0x000000010e20bd80 (void *)0x000000010e20bea0: OBJC_METACLASS_$__TtC22TestingViewControllers14ViewController)
{
instance_type = 0x00007fe22c92a290 -> 0x000000010e20bd80 (void *)0x000000010e20bea0: OBJC_METACLASS_$__TtC22TestingViewControllers14ViewController
}

спросил(а) 2020-03-04T17:43:30+03:00 6 месяцев, 3 недели назад
1
Решение
158

Я придумал лучшее решение, чем сделать все публичным. На самом деле вам просто нужно использовать раскадровку, которая исходит из тестового пакета, вместо того, чтобы использовать nil (заставляя его исходить из основного целевого пакета). Я сделал более подробное сообщение здесь, если кто-то заинтересован в чтении немного дальше.

var storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: NSBundle(forClass: self.dynamicType))
vc = storyboard.instantiateViewControllerWithIdentifier("LoginVC") as LoginViewController
vc.loadView()

ответил(а) 2020-03-04T17:56:13.123509+03:00 6 месяцев, 3 недели назад
41

Установили ли вы раскадровку, если у вас есть, тогда вы можете сделать это следующим образом.


Вам также нужно переименовать класс контроллера вида, например, здесь MyAppViewController использует основную раскадровку вместо стандартного класса viewcontroller, а затем устанавливает идентификатор storyboardID, например, MyappVC


  var sut : MyAppViewController!

override func setUp() {
super.setUp()

// get a reference to storyboard and the correct
// viewcontroller inside it. Remember to add
// storyboardID in this case "MyappVC"

let StoryBoard = UIStoryboard.init(name: "Main", bundle: nil)
sut = StoryBoard.instantiateViewControllerWithIdentifier("Myapp VC")as!
CalculatorViewController

//trigger viewDidLoad()
_ = sut.view

ответил(а) 2020-03-04T17:43:30+03:00 6 месяцев, 3 недели назад
40

Спасибо @Derrik Hathaway за ключ к решению. Приложение и тестовая цель - разные модули.


Мое приложение имеет неудачное имя TestingViewControllers. Чтобы исправить ошибку, я внесла следующие изменения и сделал класс ViewController a public еще в коде приложения.


Добавлена ​​эта строка для проверки:


import TestingViewControllers

Измените тестовый пример:


func testExample() {

var storyBoard: UIStoryboard?
var anyVC: AnyObject?
var viewController: TestingViewControllers.ViewController?

storyBoard = UIStoryboard(name:"Main", bundle: nil)
XCTAssert(storyBoard != nil, "Test Not Configured Properly")

anyVC = storyBoard?.instantiateInitialViewController()
viewController = anyVC as? TestingViewControllers.ViewController
XCTAssert(viewController != nil, "Test Not Configured Properly")

// This is an example of a functional test case.
XCTAssert(true, "Pass")

}


Прохождение тестового теста

ответил(а) 2020-03-04T17:43:30+03:00 6 месяцев, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема