UI Testing: tap() not triggering the button's action

Hello. I've been struggling to make some simple (and some not that simple) UI tests for iOS with the UITesting (XCUI) framework. While I've found the lack of official documentation a bit disturbing, a more serious hurdle has been .tap() not triggering the button action. I have enough experience in coding not to blame the frameworks (especially those of major player such as Apple) but I cannot see where the flaw in my setup is as I have read dozens of similar samples on the internet. So in a nutshell my problem is: calling app.buttons["foo"].tap() occasionally does not trigger the button action. If I clean out stuff under DerivedData, make a Clean and restart everything, it works once or twice and then starts failing 100% again. Please find my test case below:


import XCTest
class UITestPocUITests: XCTestCase {
    var app: XCUIApplication!
    func waitForElementToExist(element: XCUIElement, seconds waitSeconds: Double) {
        let exists = NSPredicate(format: "exists == true")
        expectationForPredicate(exists, evaluatedWithObject: element, handler: nil)
        waitForExpectationsWithTimeout(waitSeconds, handler: nil)
    }
    func waitForLabelValue(element: XCUIElement, value: String, seconds waitSeconds: Double) {
        let exists = NSPredicate(format: "label == %@", value)
        expectationForPredicate(exists, evaluatedWithObject: element, handler: nil)
        waitForExpectationsWithTimeout(waitSeconds, handler: nil)
    }
    override func setUp() {
        super.setUp()
        /
        continueAfterFailure = false
        /
        app = XCUIApplication()
        app.launch()
        / 
    }
   
    override func tearDown() {
        /
        super.tearDown()
        /
        app.terminate()
        app = nil
    }
    func testShowMessage() {
/
/
/
        let button = app.buttons["SHOW MESSAGE"]
        print("exists = \(button.exists), hittable = \(button.hittable)")
        app.buttons["SHOW MESSAGE"].tap()
        let messageLabel = app.staticTexts["messageLabel"]
        waitForLabelValue(messageLabel, value: "This is a message", seconds: 3.0)
        /
        /
/ 
/
/
        /
    }
    func testDealloc() {
        /
        app.buttons["SHOW SECOND"].tap()
        let navBar = app.navigationBars["Items"]
        waitForElementToExist(navBar, seconds: 3)
        let expectation = expectationWithDescription("Second view controller must have been deallocated")
        let ipc = SimpleIPC()
        ipc.listen { message in
            print("Got message: \(message)")
            if message == "SecondViewController.deinit" {
                print("Second view controller deinitialized - expectation fulfilled!")
                expectation.fulfill()
            }
        }
        /
        /
        navBar.buttons["First"].tap()
        waitForExpectationsWithTimeout(5) { error in
            print("Error: \(error)")
        }
    }
}


I've been running this under Xcode 9.3.1, iOS simulator, deployment target: iOS 9.3.


- Matti

Ok so it seems this can be kludge-fixed by adding a sleep(1); in the setup functions 🙂


See: http://stackoverflow.com/questions/37276597/xcuielement-tap-not-working/37320452#37320452

UI Testing: tap() not triggering the button's action
 
 
Q