Swift2 UI Test - Wait for Element to Appear

前端 未结 6 1128
逝去的感伤
逝去的感伤 2021-02-13 15:40

I want to have a test pause and wait for an element to appear on screen before proceeding.

I don\'t see a good way to create an expectation for this and wait using

相关标签:
6条回答
  • 2021-02-13 16:09

    In expectationForPredicate(predicate: evaluatedWithObject: handler:) you don't give an actual object, but a query to find it in the view hierarchy. So, for example, this is a valid test:

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

    Check out UI Testing Cheat Sheet and documentation generated from the headers (there is no official documentation at the moment), all by Joe Masilotti.

    0 讨论(0)
  • 2021-02-13 16:11

    Based on onmyway133 code I came up with to extensions (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]
      }
    }
    

    So on your call site you can use:

    wait(for: app.getElement(withIdentifier: "ViewController"), timeout: 10)
    
    0 讨论(0)
  • 2021-02-13 16:16

    You can use this, in 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)
    }
    

    In Xcode 9, iOS 11, you can use the new API waitForExistence

    0 讨论(0)
  • 2021-02-13 16:29

    This question was asked about Swift2 but it's still a top search result in 2019 so I wanted to give an up-to-date answer.

    With Xcode 9.0+ things are a bit simpler thanks to waitForExistence:

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

    WebViews Example:

    let app = XCUIApplication()
    let webViewsQuery = app.webViews
    let myButton = webViewsQuery.staticTexts["My Button"]
    XCTAssertTrue(myButton.waitForExistence(timeout: 10))
    sleep(1)
    myButton.tap()
    
    0 讨论(0)
  • 2021-02-13 16:31

    For Xcode 8.3 and later you can wait for expectation with a new class - XCTWaiter, an example test looks like this:

    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 for more information.

    0 讨论(0)
  • 2021-02-13 16:33

    It doesn't take an already existing element. You just need to define the following predicate:

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

    Then just use this predicate in your expectation. Then of course wait on your expectation.

    0 讨论(0)
提交回复
热议问题