Check the Position of the Xcuielement on Screen While Testing iOS Application Using Xctest

Check the position of the XCUIElement on screen while testing iOS Application using XCTest

XCUIElement has a property frame which you can use to find the coordinates of the element in question.

let button = XCUIApplication().buttons["someButton"]
let frame = button.frame
let xPosition = frame.origin.x
let yPosition = frame.origin.y

There are other ways of retrieving different points relative to the frame, which is a CGRect, such as midX and midY, depending on how you want to assert the position of the element.

You should be aware that XCTest is a functional UI testing framework, and if you are using it for asserting the position of an element, the position will probably be different per device/simulator which may make your tests brittle.

UITesting Xcode 7: How to tell if XCUIElement is visible?

Looks like this is a known bug :-(

https://forums.developer.apple.com/thread/9934

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

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.

Is there a way to find if the XCUIElement has focus or not?

I little bit late for the party :) However as far as I can see from dumping the variable XCUIElement it has one interesting property:

property name: hasKeyboardFocus

property type: TB,R

So you can check if your element has focus the following way:

let hasFocus = (yourTextField.value(forKey: "hasKeyboardFocus") as? Bool) ?? false

NB: you can dump the property variables of any NSObject sublass with following extension:

extension NSObject {
func dumpProperties() {
var outCount: UInt32 = 0

let properties = class_copyPropertyList(self.dynamicType, &outCount)
for index in 0...outCount {
let property = properties[Int(index)]
if nil == property {
continue
}
if let propertyName = String.fromCString(property_getName(property)) {
print("property name: \(propertyName)")
}
if let propertyType = String.fromCString(property_getAttributes(property)) {
print("property type: \(propertyType)")
}
}
}
}

Update: Properties dump, Swift 4:*

extension NSObject {
func dumpProperties() {
var outCount: UInt32 = 0

let properties = class_copyPropertyList(type(of: self), &outCount)
for index in 0...outCount {
guard let property = properties?[Int(index)] else {
continue
}
let propertyName = String(cString: property_getName(property))
print("property name: \(propertyName)")
guard let propertyAttributes = property_getAttributes(property) else {
continue
}
let propertyType = String(cString: propertyAttributes)
print("property type: \(propertyType)")
}
}
}

XCTest - UI Testing with XCUIElement using pinch gesture on custom coordinates?

I figured out that I can (but don't want to) add another empty view on top of my blueView with constraints to half of the size of it (see yellowish rectangle in the illustration below). This works for all my cases so far because no other view overlaps that far. It looks something like this:

UI with emtpy view for pinch gestures

Executing a pinchWithScale on that empty view works and actually pinches the blueView.

This is a very ugly solution, since I've to add a view which is solely for UI testing.

If anyone has a hint on how to remove it for the release build let me know.

Update

I made a build step running a script which adds this view only when executing the UI automation test target. After the execution the source control (e.g. git reset HEAD~) is used to undo the added view.



Related Topics



Leave a reply



Submit