简体   繁体   中英

Using a conditional in XCUITest doesn't seem to work

I have launch arguments set up to clear user defaults and log out between tests however, half the time this doesn't seem to work. I have been chasing down a possible bug that might be the root cause but in the mean time I would like to have less flaky tests so developers have more confidence in them. So I added a conditional around the login step that should only execute if the login button exists. When running the tests, its like the if statement is ignored completely an the tests look for the login button and then fail when its not found.

Code:

   func login() {
    app.buttons["Have an account? Log in"].tap()
    let emailAddressTextField = app.textFields["Email Address"]
    let passwordSecureTextField = app.secureTextFields["Password"]

    emailAddressTextField.tap()
    emailAddressTextField.typeText(EMAIL_ALPHA_USER)
    passwordSecureTextField.tap()
    passwordSecureTextField.typeText(PASSWORD)

    if app.staticTexts["Success!"].waitForExistence(timeout: 5) {
        app.buttons["OK"].tap()
    }
   }

   func testTapControlMode() {
     if app.buttons["Have and Account?"].exists {
        login()
     }
    // ... proceed with test
    }

What am I not getting here? I've tried using .isHittable and that doesn't work either. I've put breakpoints in the tests and printed the result of app.buttons["name"].exists and it returns false whereas .isHittable returns some error. So it seems like .exists here should do what I expect.

In many cases XCUITest Framework doesn't wait long enough before view becomes available for interaction. To fix that, you should write some wait logic, best with writing extension for the XCTestCase class, like this:

extension XCTestCase {

    enum Condition: String {
        case appear = "exists == true"
        case disappear = "exists == false"
    }

    func waitFor(_ element: XCUIElement, to condition: Condition) -> Bool {
        let predicate = NSPredicate(format: condition.rawValue)
        let expectationConstant = expectation(for: predicate, evaluatedWith: element, handler: nil)

        let result = XCTWaiter().wait(for: [expectationConstant], timeout: 5)
        return result == .completed
    }
}

Then, you could have something like this in your test:

func testTapControlMode() {
    let haveAnAccountButton = app.buttons["Have and Account?"]
    if waitFor(haveAnAccountButton, to: .appear) {
        login()
    }
    // ... proceed with test
}

And in your login method:

func login() {
    app.buttons["Have an account? Log in"].tap()
    let emailAddressTextField = app.textFields["Email Address"]
    let passwordSecureTextField = app.secureTextFields["Password"]
    let successLabel = app.staticTexts["Success!"]

    emailAddressTextField.tap()
    emailAddressTextField.typeText(EMAIL_ALPHA_USER)
    passwordSecureTextField.tap()
    passwordSecureTextField.typeText(PASSWORD)

    if waitFor(successLabel, to: .appear) {
        app.buttons["OK"].tap()
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM