Как проверить наличие статического текста, отображаемого в сети в тестах пользовательского интерфейса в Xcode?

Я использую API-интерфейсы пользовательского интерфейса, представленные в Xcode 7 XCTest. На моем экране у меня есть текст, загруженный из сети.

Тест не выполняется, если я просто проверяю его с помощью свойства exists.

XCTAssert(app.staticTexts["Text from the network"].exists) // fails

Это действительно работает, если я сначала отправлю кран или любое другое событие в текст следующим образом:

app.staticTexts["Text from the network"].tap()
XCTAssert(app.staticTexts["Text from the network"].exists) // works

Похоже, если я просто позвоню exists, он сразу же оценит его и завершит неудачу, потому что текст еще не загружен из сети. Но я думаю, что когда я вызываю метод tap(), он ждет появления текста.

Есть ли лучший способ проверить наличие текста, который доставлен из сети?

Что-то вроде (этот код не будет работать):

XCTAssert(app.staticTexts["Text from the network"].eventuallyExists)

Ответы

Ответ 1

Xcode 7 Beta 4 добавила встроенную поддержку асинхронных событий. Ниже приведен краткий пример того, как ждать появления UILabel.

XCUIElement *label = self.app.staticTexts[@"Hello, world!"];
NSPredicate *exists = [NSPredicate predicateWithFormat:@"exists == 1"];

[self expectationForPredicate:exists evaluatedWithObject:label handler:nil];
[self waitForExpectationsWithTimeout:5 handler:nil];

Сначала создайте запрос для ожидания метки с текстом "Hello, world!". появиться. Предикат соответствует, когда существует элемент (element.exists == YES). Затем передайте предикат и оцените его от метки.

Если пять секунд пройдет до того, как будет выполнено ожидание, тест завершится неудачно. Вы также можете присоединить блок обработчика, который вызывается, когда ожидание не выполняется или время ожидания.

Если вы ищете дополнительную информацию о тестировании пользовательского интерфейса в целом, проверьте тестирование пользовательского интерфейса в Xcode 7.

Ответ 2

Если я правильно понимаю, что целевой текст уже отображается, когда вы проверяете его существующий, вы можете попробовать использовать свойство hittable.

Ответ 3

Swift 3:

let predicate = NSPredicate(format: "exists == 1")
let query = app!.staticTexts["identifier"]
expectation(for: predicate, evaluatedWith: query, handler: nil)
waitForExpectations(timeout: 5, handler: nil)

Он будет непрерывно проверять в течение 5 секунд, отображается ли этот текст или нет.

Как только он найдет текст в течение менее 5 секунд, он выполнит дальнейший код.

Ответ 4

XCode9 имеет метод waitForExistence (timeout: TimeInterval) XCUIElement

extension XCUIElement {
    // A method for tap element
    @discardableResult
    func waitAndTap() -> Bool {
        let _ = self.waitForExistence(timeout: 10)
        let b = self.exists && self.isHittable
        if (b) {
            self.tap()
        }
        return b
    }
}

// Ex:
if (btnConfig.waitAndTap() == true) {
    // Continue UI automation
} else {
    // `btnConfig` is not exist or not hittable.
}

Но я столкнулся с другой проблемой, element существует, но не является hittable. Поэтому я продлеваю метод, чтобы подождать, пока элемент не станет недоступным.

extension XCTestCase {
    /// Wait for XCUIElement is hittable.
    func waitHittable(element: XCUIElement, timeout: TimeInterval = 30) {
        let predicate = NSPredicate(format: "isHittable == 1")
        expectation(for: predicate, evaluatedWith: element, handler: nil)
        waitForExpectations(timeout: timeout, handler: nil)
    }
}

// Ex:
// waitHittable(element: btnConfig)