Swift中IBActions和IBOutlets的XCT测试(可选项)

3

我想知道在Swift中测试IBOutlets和IBActions的最佳方法,因为IBActions是可选的。

我目前正在重写一个我最初用Swift编写的项目,但这次我想使用XCT单元测试。

我已经遇到了一个小问题,涉及到对IBOutlets和IBActions进行测试。以下是我的代码:

override func setUp() {
    super.setUp()

    storyboard = UIStoryboard(name: "Main", bundle: nil)
    mainMenuViewController = storyboard.instantiateViewControllerWithIdentifier("MainMenuViewController") as! MainMenuViewController

    let dummy = mainMenuViewController.view // force loading subviews and setting outlets

    mainMenuViewController.viewDidLoad()
}

override func tearDown() {
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    super.tearDown()
}

func testWhetherTranslationGameModeButtonExists() {
    XCTAssert(mainMenuViewController.translateButton != nil, "translate button should exist at all times");
}

func testWhetherTranslateGameModeButtonTitleIsCorrect() {

    let title: String? = mainMenuViewController.translateButton?.titleLabel?.text

    if let unwrappedTitle = title {
        XCTAssertTrue(unwrappedTitle == "Translate Mode", "title of translate button should be Translate Mode")
    }
    else {
        XCTFail("Value isn't set")
    }
}

func testTranslateGameModeButtonIBAction() {

    if let unwrappedButton = mainMenuViewController.translateButton {
        if let actions: Array<String> = unwrappedButton.actionsForTarget(mainMenuViewController, forControlEvent: UIControlEvents.TouchUpInside) as? Array<String> {

            contains(actions, "")
            XCTAssertTrue(contains(actions, "translateButtonPressed"), "translate button should call method translateButtonPressed")
        }
        else {
            XCTFail("button is set but the IBAction is not set")
        }
    }
    else {
        XCTFail("button isn't set and therefore IBAction can not function")
    }
}

正如您所见,第一个测试检查翻译游戏模式按钮是否存在。这个测试很好用。

然而,在标题测试中,我需要展开按钮并测试标签。这似乎是两个测试。

当涉及IBAction时,我需要展开可选类型以使用按钮,并对成功和失败进行XCTAssert。因此,每次使用此按钮之前,我都需要展开它才能使用它。这似乎非常重复,再次看起来像多个测试。

我想知道这是否是正确的方法,或者有更好的方法来处理可选项的测试。


当我将代码更改为let storyboard = UIStoryboard(name: "Main", bundle: NSBundle(forClass: self.dynamicType))时,我在设置故事板UIStoryboard时遇到了错误= UIStoryboard(name: "Main", bundle: nil)??。这样更改后就可以正常工作了。您知道为什么会发生这种情况吗? - user4790024
当我使用 NSBundle(forClass: self.dynamicType)) 时,我遇到了相同的错误。还不确定原因。 - pls
不好意思,我的意思是当我将bundle设置为nil时出现了错误? - user4790024
2个回答

0

我不明白为什么你的按钮是可选的。 如果你在控制器中通过拖动来创建输出口,你会得到一个非可选变量。

我是这样设置我的控制器测试的: https://gist.github.com/racer1988/bf15448efde47e627dac

我从这里得到了灵感: http://natashatherobot.com/ios-testing-view-controllers-swift/

然后为了完成覆盖,你需要编写三个测试:

  • 如果输出口被设置
  • 如果输出口连接到了操作
  • 如果操作正在发挥作用

这样,你就可以测试所有内容,而无需模拟点击等操作。

func testOutletExist() {
    XCTAssertNotNil(viewController.outletName)
}

func testActionIsConnected() {
    XCTAssertTrue(viewController.outlet.action == "IBactionName:")
}

func testActionCode() {
    let result = IBactionName()
    XCTAssertSomething(result)
}

马可,你到底在哪里找到了outlet.action?我希望它存在。 - Julio Bailon
@JulioBailon 对不起,在这个例子中我正在测试菜单栏 https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIBarButtonItem_Class/#//apple_ref/occ/instp/UIBarButtonItem/action - Marco Pappalardo

0
如果有可能的话,请使用XCode 7。 使用XCode 7,您可以轻松进行UI测试:
文件->新建->目标->iOS->测试iOS UI测试包
生成的代码具有一些如何使用它的提示。 基本上,您将光标放在测试方法中,然后点击红色记录按钮。
因此,您可以模拟(几乎)任何用户操作。 当您为可访问性命名UI元素时,生成的代码更易读。
由于您正在测试控制器的自然栖息地:应用程序内部,因此您的测试结果更加有意义。
(虽然在XCode 7之前就已经有过了,但是使用XCode 7确实很容易)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接