XCUIElement tap()无效

时间:2016-05-17 12:44:02

标签: ios swift integration-testing xcode-ui-testing

我有一个非常简单的XCTestCase实现,可以测试按下按钮并希望显示一个Alert控制器。问题是tap()方法不起作用。在相关按钮的IBAction中放置断点我意识到逻辑甚至不会被调用。

class uitestsampleUITests: XCTestCase {

    var app: XCUIApplication!

    override func setUp() {
        super.setUp()
        continueAfterFailure = false
        app = XCUIApplication()
        app.launch()
    }

    func testButton() {
        let button = app.buttons["Button"]
        button.tap()

        expectationForPredicate(NSPredicate(format: "exists == 1"), evaluatedWithObject: button, handler: nil)
        waitForExpectationsWithTimeout(5.0, handler: nil)
    }
}

此外,复制button.tap()指令会使测试通过,如下所示:

    func testButton() {
        let button = app.buttons["Button"]
        button.tap()
        button.tap()

        expectationForPredicate(NSPredicate(format: "exists == 1"), evaluatedWithObject: button, handler: nil)
        waitForExpectationsWithTimeout(5.0, handler: nil)    
    }

我在Xcode 7.3.1中遇到这个问题我错过了什么吗?这是一个错误吗?

5 个答案:

答案 0 :(得分:8)

因此,一名Apple工程师回复了我的错误报告:

  

第二种可能性是你遇到了一个问题   有时会发生应用程序完成启动的地方但是   启动画面不会立即消失,事件也会发送到   应用程序处理不当。

     

要尝试解决该问题,请考虑稍加延迟   测试的开始(睡眠(1)应该足够了。)

所以我做了它,现在它起作用了:

override func setUp() {
    super.setUp()
    continueAfterFailure = false
    app = XCUIApplication()
    app.launch()
    sleep(1)
}

答案 1 :(得分:4)

对于可命中的UIWebView,在我通过坐标完成之前,点击无效:

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

希望它有助于某人

P.S。也适用于不可打击的项目,如标签等。

答案 2 :(得分:3)

我有类似的东西。对我来说问题是,我试图点击的元素,由于某种原因有时不是hittable

来自Apple的文档:

  

将tap事件发送到为元素计算的可命中点。

因此,如果某个元素不是hittable,则点按操作不会做太多,这会破坏测试用例的逻辑。

为了解决这个问题,在我点击某些内容之前,我会等到相应的元素变得可以击中。很简单。

#import <XCTest/XCTest.h>

@interface XCUIElement (Tap)

- (void)tapInTestCase:(XCTestCase *)testCase;

@end

@implementation XCUIElement (Tap)

- (void)tapInTestCase:(XCTestCase *)testCase
{
    // wait until the element is hittable
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"hittable == true"];
    [testCase expectationForPredicate:predicate evaluatedWithObject:element handler:nil];
    [testCase waitForExpectationsWithTimeout:5.0f handler:nil];

    // and then tap
    [self tap];
}

@end

答案 3 :(得分:0)

对我来说,最可靠的方法是在元素未被正确利用的地方添加sleep(1)。使用值小于usleep的{​​{1}}函数会导致不可靠的行为,例如正确的测试会随机失败。

答案 4 :(得分:0)

您可以wait在元素加载时创建此扩展名:

import XCTest

extension XCUIElement {
    func tap(wait: Int, test: XCTestCase) {
        if !isHittable {
            test.expectation(for: NSPredicate(format: "hittable == true"), evaluatedWith: self, handler: nil);
            test.waitForExpectations(timeout: TimeInterval(wait), handler: nil)
        }
        tap()
    }
}

像这样使用:

app.buttons["start"].tap(wait: 20, test: self)