【问题标题】:Swift2 UI Test - Wait for Element to AppearSwift2 UI 测试 - 等待元素出现
【发布时间】:2015-12-02 16:29:10
【问题描述】:

我想暂停测试并等待某个元素出现在屏幕上,然后再继续。

我没有看到一个好的方法来为此创建期望并等待使用

public func waitForExpectationsWithTimeout(timeout: NSTimeInterval, handler: XCWaitCompletionHandler?)

我一直在使用的创建期望的方法是

public func expectationForPredicate(predicate: NSPredicate, evaluatedWithObject object: AnyObject, handler: XCPredicateExpectationHandler?) -> XCTestExpectation

但这需要一个已经存在的元素,而我想让测试等待一个尚不存在的元素。

有人知道最好的方法吗?

【问题讨论】:

    标签: swift swift2 xcode-ui-testing


    【解决方案1】:

    expectationForPredicate(predicate: evaluatedWithObject: handler:) 中,您不提供实际对象,而是提供在视图层次结构中查找它的查询。因此,例如,这是一个有效的测试:

    let predicate = NSPredicate(format: "exists == 1")
    let query = XCUIApplication().buttons["Button"]
    expectationForPredicate(predicate, evaluatedWithObject: query, handler: nil)
    
    waitForExpectationsWithTimeout(3, handler: nil)
    

    查看由标题生成的 UI Testing Cheat Sheetdocumentation(目前没有官方文档),均由 Joe Masilotti 编写。

    【讨论】:

    • 我可以发誓我在早期版本的 UI 测试中尝试过这个,但没有成功,哦,好吧,谢谢
    • 从 Xcode 8.3 开始(目前仍是测试版),有一个更好的方法来做到这一点 - XCTestWaiter。发布时我会更新我的答案。再次感谢 Joe Masilotti 在主题 masilotti.com/xctest-waiting 中提供的丰富资源
    • 出于历史原因,我决定不更新当前答案,而是发布了一个新答案以保留旧答案。请考虑将stackoverflow.com/a/47181750/2777364 标记为已接受的答案
    【解决方案2】:

    这个问题是关于 Swift2 的,但它仍然是 2019 年的热门搜索结果,所以我想给出一个最新的答案。

    感谢waitForExistence,有了 Xcode 9.0+,事情变得更简单了:

    let app = XCUIApplication()
    let myButton = app.buttons["My Button"]
    XCTAssertTrue(myButton.waitForExistence(timeout: 10))
    sleep(1)
    myButton.tap()
    

    WebView 示例:

    let app = XCUIApplication()
    let webViewsQuery = app.webViews
    let myButton = webViewsQuery.staticTexts["My Button"]
    XCTAssertTrue(myButton.waitForExistence(timeout: 10))
    sleep(1)
    myButton.tap()
    

    【讨论】:

      【解决方案3】:

      你可以在 Swift 3 中使用它

      func wait(element: XCUIElement, duration: TimeInterval) {
        let predicate = NSPredicate(format: "exists == true")
        let _ = expectation(for: predicate, evaluatedWith: element, handler: nil)
      
        // We use a buffer here to avoid flakiness with Timer on CI
        waitForExpectations(timeout: duration + 0.5)
      }
      

      在 Xcode 9、iOS 11 中,您可以使用新的 API waitForExistence

      【讨论】:

        【解决方案4】:

        它不需要已经存在的元素。您只需要定义以下谓词:

        let exists = NSPredicate(format: "exists = 1")

        然后在你的期望中使用这个谓词。然后当然是等待你的期望。

        【讨论】:

        • 我在 Objective-C 中有一个例子,而不是在 swift 中。如果您需要,我可以包含它。
        【解决方案5】:

        对于 Xcode 8.3 及更高版本,您可以等待新类的期望 - XCTWaiter,示例测试如下所示:

        func testExample() {
          let element = // ...
          let predicate = NSPredicate(format: "exists == true")
          let expectation = XCTNSPredicateExpectation(predicate: predicate, object: element)
        
          let result = XCTWaiter().wait(for: [expectation], timeout: 1)
          XCTAssertEqual(.completed, result)
        }
        

        Read the documentation 了解更多信息。

        【讨论】:

          【解决方案6】:

          基于onmyway133 code 我想出了扩展(Swift 3.2):

          extension XCTestCase {
            func wait(for element: XCUIElement, timeout: TimeInterval) {
              let p = NSPredicate(format: "exists == true")
              let e = expectation(for: p, evaluatedWith: element, handler: nil)
              wait(for: [e], timeout: timeout)
            }
          }
          
          extension XCUIApplication {
            func getElement(withIdentifier identifier: String) -> XCUIElement {
              return otherElements[identifier]
            }
          }
          

          因此,您可以在呼叫站点上使用:

          wait(for: app.getElement(withIdentifier: "ViewController"), timeout: 10)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2022-08-12
            • 2016-05-09
            • 2013-01-12
            • 1970-01-01
            • 1970-01-01
            • 2020-03-29
            • 1970-01-01
            相关资源
            最近更新 更多