Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xcode7 | Xcode UI Tests | How to handle location service alert?

I am writing UI Test Cases for one one of my app using the XCUIApplication, XCUIElement and XCUIElementQuery introduced in Xcode7/iOS 9.

I have hit a road block. One of the screens in test case requires iOS's Location Services. As expected the user is prompted about allowing use of location service with alert titled: Allow “App name” to access your location while you use the app? with Allow & Don't Allow buttons.

Problem is or so it seems that since the alert is presented by OS itself it is not present in Application's element sub-tree.

I have logged following:

print("XYZ:\(app.alerts.count)")//0 var existence = app.staticTexts["Allow “App Name” to access your location while you use the app?"].exists print("XYZ:\(existence)")//false existence  = app.buttons["Allow"].exists print("XYZ:\(existence)") //false 

Even UI recording generated similar code:

XCUIApplication().alerts["Allow “App Name” to access your location while you use the app?"].collectionViews.buttons["Allow"].tap() 

I have not found any API that can get me past this problem. For example:

  • Tap at a position on the screen
  • Get alerts outside the app

So how can I get past this? Is there a way to configure Test Targets so that Location Service Authorization is not required.

like image 463
Taha Samad Avatar asked Jul 31 '15 12:07

Taha Samad


People also ask

How do you run a UI test?

Go to File > New > Target. Then, search for UI Testing Bundle. Select Unit Testing Bundle and then click Next. As UI tests take time, it is usually best to stop immediately when a failure occurs.

What is XCTest in iOS?

Overview. Use the XCTest framework to write unit tests for your Xcode projects that integrate seamlessly with Xcode's testing workflow. Tests assert that certain conditions are satisfied during code execution, and record test failures (with optional messages) if those conditions aren't satisfied.

What is XCUITest?

What is XCUITest/XCTest? XCUITest is a native framework for UI testing on iOS mobile devices. Since XCUITest is baked right into Xcode IDE, it provides the fastest possible testing for iOS devices. However, there are several limitations to be aware of in addition to the several major benefits.


2 Answers

Xcode 9

    let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")     let allowBtn = springboard.buttons["Allow"]     if allowBtn.exists {         allowBtn.tap()     } 

Xcode 8.3.3

    _ = addUIInterruptionMonitor(withDescription: "Location Dialog") { (alert) -> Bool in         alert.buttons["Allow"].tap()         return true     }     app.buttons["Request Location"].tap()     app.tap() // need to interact with the app for the handler to fire 

Note that it is a bit different as the method name now is addUIInterruptionMonitor and takes withDescription as an argument

Xcode 7.1

Xcode 7.1 has finally fixed a issue with system alerts. There are, however, two small gotchas.

First, you need to set up a "UI Interuption Handler" before presenting the alert. This is our way of telling the framework how to handle an alert when it appears.

Second, after presenting the alert you must interact with the interface. Simply tapping the app works just fine, but is required.

addUIInterruptionMonitorWithDescription("Location Dialog") { (alert) -> Bool in     alert.buttons["Allow"].tap()     return true }  app.buttons["Request Location"].tap() app.tap() // need to interact with the app for the handler to fire 

The "Location Dialog" is just a string to help the developer identify which handler was accessed, it is not specific to the type of alert.

Xcode 7.0

The following will dismiss a single "system alert" in Xcode 7 Beta 6:

let app = XCUIApplication() app.launch() // trigger location permission dialog  app.alerts.element.collectionViews.buttons["Allow"].tap() 

Beta 6 introduced a slew of fixes for UI Testing and I believe this was one of them.

Also note that I am calling -element directly on -alerts. Calling -element on an XCUIElementQuery forces the framework to choose the "one and only" matching element on the screen. This works great for alerts where you can only have one visible at a time. However, if you try this for a label and have two labels the framework will raise an exception.

like image 97
Joe Masilotti Avatar answered Sep 20 '22 15:09

Joe Masilotti


This was the only thing that worked for me. Using Xcode 9 fwiw.

Also probably relevant that I was already using addUIInterruptionMonitor for a different alert. I tried reordering them and it didn't make a difference. Could be that it's a problem in 9 when you have two, or could be I was using them wrong. In any event the code below worked. :)

let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard") let allowBtn = springboard.buttons["Allow"] if allowBtn.exists {     allowBtn.tap() } 
like image 43
Joe Susnick Avatar answered Sep 17 '22 15:09

Joe Susnick