无法在Xcode UI Test中点击UIBarButtonItem

时间:2015-12-23 00:28:08

标签: ios objective-c xcode xcode-ui-testing

我的导航栏为"添加"按钮就可以了,我需要让Xcode的UI测试点击该按钮,在它打开的视图控制器中执行测试。我以编程方式添加按钮:

UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(showAddVC)];
self.navigationItem.rightBarButtonItem = addButton;

在我的测试中,我有:

XCUIApplication *app = [[XCUIApplication alloc] init];
XCTAssert([app.buttons[@"Add"] exists]); // <-- This passes, so the test runner does see the button.

但是当我尝试使用其中任何一个来点击它时:

// Generated using the test recorder
[app.navigationBars[@"App Title"].buttons[@"Add"] tap];

或:

// Same expression used with the XCTAsset earlier
[app.buttons[@"Add"] tap];    

什么都没发生。点击按钮时应该执行的操作不会发生。我尝试在行之间添加一些sleep(5)来让应用加载,但这并没有多大帮助。

这是测试日志:

Test Case '-[xx]' started.
    t =     0.00s     Start Test
    t =     0.00s     Set Up
2015-12-22 16:25:02.898 XCTRunner[10978:384690] Continuing to run tests in the background with task ID 1
    t =     0.94s         Launch xx
    t =     1.01s             Waiting for accessibility to load
    t =     3.45s             Wait for app to idle
    t =     9.02s     Tap "Add" Button
    t =     9.02s         Wait for app to idle
    t =    39.07s             Assertion Failure: UI Testing Failure - App failed to quiesce within 30s
xx: error: -[xx] : UI Testing Failure - App failed to quiesce within 30s

4 个答案:

答案 0 :(得分:5)

上述答案都不适合我。经过几个小时的奋斗之后,最终使它发挥作用的是重复敲击。试试这个:

[app.navigationBars[@"App Title"].buttons[@"Add"] tap];
[app.navigationBars[@"App Title"].buttons[@"Add"] tap];

虽然上面最初对我有用,但我发现有时第一个水龙头工作,这将导致两个水龙头。我的解决方案是改为点击在UI测试开始时不会触发任何操作的任意UI元素,然后正常进行。我认为第一次点击适用于某些设备,或者可能是在第一次UI测试运行之后。

答案 1 :(得分:1)

在您的情况下,exists的测试似乎不够。在尝试点击按钮之前,请等待按钮hittable

    expectationForPredicate(predicate, evaluatedWithObject: element, handler: nil)
    waitForExpectationsWithTimeout(timeoutSeconds, handler: nil)

在你的情况下会是:

    expectationForPredicate(NSPredicate(format: "hittable == YES"), evaluatedWithObject: [app.buttons[@"Add"], handler: nil)
    waitForExpectationsWithTimeout(15, handler: nil)
    [app.buttons[@"Add"] tap];  

这将暂停waitForExpectationWithTimeout之后的代码执行,直到该谓词对给定元素满意为止。

否则,在极端情况下,我发现在尝试与某些组件交互时有时会发生错误。这些发生的方式,原因和时间有点神秘,但它们似乎与某些组件有些一致,涉及UINavigationBars的事情似乎更频繁地发生。

为了克服这些问题,我发现使用此扩展程序有时会有效。

extension XCUIElement {

    /* Sends a tap event to a hittable/unhittable element. Needed to get past bug */
    func forceTapElement() {
        if hittable {
            tap()
        }
        else {
            let coordinate: XCUICoordinate = coordinateWithNormalizedOffset(CGVectorMake(0.0, 0.0))
            coordinate.tap()
        }
    }
}

答案 2 :(得分:1)

对于Alex的回答不起作用的人,请尝试:

extension XCUIElement {
    func forceTap() {
        coordinate(withNormalizedOffset: CGVector(dx:0.5, dy:0.5)).tap()
    }
}

我刚遇到UIWebView的问题,这个问题是可以触及的,但是直到通过坐标完成它才开始工作

答案 3 :(得分:0)

一种可能性是您的条形按钮项目推送具有刷新控件的新视图控制器 - 您可能只在iPad上遇到此情况,只有您的条形按钮项目会推到拆分视图控制器的细节部分。获取项目后,您可能会停止刷新控件,而这些控件首先不会刷新。 Xcode的自动化确实可以解决这个问题,睡眠/超时也无济于事。

因此,要解决此问题,请在主应用程序上,在结束刷新之前始终检查刷新控件是否刷新。我也想首先检查一下它是不是nil:如果你使用的是Swift,if-let where一下子做了所有这些,那么你的朋友应该在这里:

if let refresh = self.refreshControl where refresh.refreshing {
  refresh.endRefreshing()
}