-
Notifications
You must be signed in to change notification settings - Fork 369
DeviceAgent
Apple has removed UIAutomation from Xcode 8. Our replacement for UIAutomation is DeviceAgent. DeviceAgent is based on Apple's XCUITest framework.
Our goal for this transition is 100% backward compatibility with UIAutomation. We think we are close, but we need your help to discover what is missing. Since UIAutomation is not available, all uia_*
calls now raise an error when tests are run with DeviceAgent. The text of the error will have workarounds and examples to help you transition your tests. Please read the error message and try the suggested replacements. When you find something you cannot do with DeviceAgent, please create a GitHub issue.
The short answer is almost never.
The query engine in the Calabash iOS Server (LPServer) is faster and can find more views that DeviceAgent.
In general, you should use DeviceAgent for views are outside of your application or for views that are presented by the OS. The classic examples are Safari WebView Controllers and Email Compose Controllers. Because these views are outside of your application, the LPServer that is embedded in your application cannot detect them. The DeviceAgent can, for the most part, detect these kinds of views.
Setting the CODE_SIGN_IDENTITY
is no longer necessary. The CODE_SIGN_IDENTITY
environment variable is still respected if, for some reason, you want to force a particular signing identity.
Testing on physical devices now has an additional requirement: code signing.
You must provide a valid code signing identity.
# Find the valid code signing identities
$ xcrun security find-identity -v -p codesigning
1) 18<snip>84 "iPhone Developer: Your Name (ABCDEF1234)"
2) 23<snip>33 "iPhone Distribution: Your Company Name (A1B2C3D4EF)"
3) 38<snip>11 "iPhone Developer: Your Colleague (1234ABCDEF)"
# Chose an "iPhone Developer" certificate.
$ CODE_SIGN_IDENTITY="iPhone Developer: Your Name (ABCDEF1234)" \
DEVICE_TARGET=< device udid > \
DEVICE_ENDPOINT=http://< device ip >:37265 \
bundle exec cucumber
The behavior of the swipe and flick gestures will be different.
Scenario: Flick to Go Back in UINavigationController
And I am looking at the Scrollplications page
When I full-screen flick to go back, I see the Pan menu
But flick to go back does not work with DeviceAgent
The example above demonstrates that flick gesture has different behaviors with the same arguments depending on whether the gesture is performed with UIAutomation or with DeviceAgent. The reverse is also true: a flick-to-go-back that works with DeviceAgent will not work with UIAutomation.
# Flick to go back
if uia_available?
flick( < arguments that work for UIA > )
else
flick( < arguments that work for DeviceAgent > )
end
The behavior of swipe is fairly uniform.
Scenario: Full Screen Pan
And I am looking at the Pan Palette page
Then I can swipe to go back to the Pan menu
There is probably a set of arguments for swipe that has the same behavior under UIAutomation and DeviceAgent - you will have to experiment to find the right arguments.
If you want swipes and flicks that work for both UIAutomation and DeviceAgent, we recommend trying pan
and pan_coordinates
.
API Doc | Feature | Steps | Comments |
---|---|---|---|
flick | flick.feature | flick.rb | Use swipe or pan whenever possible. |
swipe | swipe.feature | swipe.rb | DeviceAgent ignores the "swipe-delta" option |
pan_coordinates | pan.feature | pan.rb | See also pan |
DeviceAgent#query
is not a substitute for Core#query
.
You should use the new DeviceAgent only when a regular Core#query
or Core
gesture does not work.
In many apps, the view hierarchy is completely opaque (invisible) to DeviceAgent.
The obvious exceptions are views that are presented for your application by the operating system or views that are presented by SpringBoard. Some examples are Mail Compose View, Photo Roll, and Health Kit views. These views are not visible to the Calabash Server, but are visible to DeviceAgent.
DeviceAgent is based on XCUITest. In our testing, we found that XCUITest itself could not automate many apps because it could not identify individual views - the whole app appears to XCUITest as a single view. The other reason DeviceAgent#query might not return any views is that XCUITest does not return the correct visibility information about an element. You can try to use DeviceAgent#query
with the all: true
option.
You should create a GitHub issue.
- At a high level, what you are trying to do.
- Provide a screenshot of the view.
If you cannot find an equivalent DeviceAgent workaround, please create an issue and include:
- At a high level, what you are trying to do.
- The JavaScript you are trying to invoke.
====
It is not possible to make raw UIAutomation JavaScript calls.
If you are trying to make query, use the DeviceAgent query API.
device_agent.query({type: "TextField", index:1})
device_agent.query({marked: "Cancel"})
If you are trying to perform a gesture or enter text, in most cases the normal Core method will work. If a normal Core method does work, try the DeviceAgent Gesture API.
device_agent.touch({type: "TextField", index:1})
device_agent.touch({marked: "Button"})
====
uia_tap, uia_tap_mark, uia_tap_offset,
uia_double_tap, uia_double_tap_mark, uia_double_tap_offset,
uia_two_finger_tap, uia_two_finger_tap_offset,
uia_touch_hold, uia_touch_hold_offset,
uia_pan, uia_pan_offset,
uia_swipe, uia_swipe_offset, uia_flick_offset,
uia_drag_inside, uia_drag_inside_mark,
uia_pinch, uia_pinch_offset, uia_scroll_to
In most cases, you will not need to use a special DeviceAgent gesture method like you did with UIAutomation.
If a Core gesture method does not work, there is a DeviceAgent gesture API.
device_agent.touch({type: "Button", marked: "Back"})
For UIA pan gestures (flick, swipe, pan) use pan_coordinates
.
from_point = device_agent.query_for_coordinate({marked: "From"})
to_point = device_agent.query_for_coordinate({marked: "To"})
pan_coordinates(from_point, to_point)
====
There is no suggested workaround for these methods. Please review the DeviceAgent API for a replacement. If you can find no replacement, please create an issue and include:
If you are trying to make query, use the DeviceAgent query API.
device_agent.query({type: "TextField", index:1})
device_agent.query({marked: "Cancel"})
If you are trying to perform a gesture or enter text, in most cases the normal Core method will work. If a normal Core method does work, try the DeviceAgent Gesture API.
device_agent.touch({type: "TextField", index:1})
device_agent.touch({marked: "Button"})
====
Use the DeviceAgent wait API.
device_agent.wait_for_view({marked: "Cancel"})
device_agent.wait_for_no_view({marked: "Cancel"})
====
Try to use the DeviceAgent query API.
device_agent.query({marked: "Cancel"})
device_agent.query({type: "TextField", index:1})
If the DeviceAgent query API does not find the correct views, please create an issue.
====
device_agent.query({marked: "Cancel"})
device_agent.query({type: "TextField", index:1})
====
In general, you should use the the text input methods defined in Core.
In some cases you will need to use the DeviceAgent query and keyboard API.
device_agent.touch({type: "TextField", index: 1})
wait_for_keyboard
keyboard_enter_text("Hello")
It is important to note that the DeviceAgent implementations of:
* keyboard_enter_text
* keyboard_enter_char
* enter_text_in
* enter_text
* fast_enter_text
have exactly the same performance.
You should prefer enter_text
or enter_text_in
because it matches the Calabash 2.0 API.
====
We have not found a case (yet) where the the Core keyboard_visible? and wait_for_keyboard methods do not work when using DeviceAgent. If you find a case where the Core methods do not work, please create a GitHub issue.
The current DeviceAgent keyboard API is scheduled for removal. It is crucial that you report workflows that require the DeviceAgent keyboard API.
device_agent.keyboard_visible?
wait_for { device_agent.keyboard_visible? }
====
There is no replacement for this method.
====
You should not be using this method. In any context (UIA or DeviceAgent) always use the orientation methods defined in the Core API.
====
You should not use this method. If the Core send_app_to_background is not working under UIAutomation, please create a GitHub issue.
====
This method has been broken for various iOS versions and device combinations for years.
At the moment, we do not have replacement for location spoofing with DeviceAgent.
====
uia_handle_command, uia_serialize_command,
uia_serialize_arguments, uia_serialize_argument
escape_uia_string, send_uia_command
There is no replacement.