XCUIElement tap() 不起作用

问题描述 投票:0回答:7

我有一个非常简单的

XCTestCase
实现,它测试按钮上的点击并期望出现警报控制器。问题是
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 中遇到这个问题,我是否遗漏了什么?这是一个错误吗?

ios swift integration-testing xcode-ui-testing
7个回答
10
投票

因此,一位 Apple 工程师对我的错误报告做出了回应:

第二种可能性是你遇到了一个问题 有时会发生在应用程序完成启动但 启动画面不会立即消失,事件会发送到 该应用程序没有得到正确处理。

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

所以我做到了,现在它可以工作了:

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

9
投票

对于可击中的

UIWebView
,在我通过坐标完成之前,水龙头无法工作:

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

希望对某人有帮助

附注也适用于不可击中的项目,例如标签等。


5
投票

我也有类似的经历。对我来说,问题是我尝试点击的元素有时由于某种原因不是

hittable

来自Apple的文档:

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

因此,如果某个元素不是

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
投票

您可以在元素加载时

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)

1
投票

对我来说,最可靠的方法是在元素未正确点击的地方添加

sleep(1)
。使用值小于
usleep
1000
函数会导致不可靠的行为,例如正确的测试随机失败。


0
投票

就我而言,问题在于按钮样式。 我正在使用 SUI 并将 ButtonStyle 设置为

.borderless
。在我的列表中(我猜)系统点击不可点击区域。但
XCTAssertTrue(app.buttons["myButton"].isHittable)
不要抛出错误。

可能对某人有帮助


0
投票

我的按钮位于 LabeledContent 内,可点击,但我的点击未注册。我猜测系统正在点击 LabeledContent 的中心点,而不是按钮本身。以下解决了我的布局问题:

button.coordinate(withNormalizedOffset: CGVector(dx: 0.95, dy: 0.95)).tap()
© www.soinside.com 2019 - 2024. All rights reserved.