In this post, I’m going to explain how you can optimize your iOS automation scripts for native apps—and speed up test execution time significantly—by first looking at how Appium works and secondly looking at different locator strategies. I’ll also let you in on a little secret!
Here are some of the most common things I hear when I work with the open source community:
Native apps are hard to automate. One of the reasons for this is that native iOS and Android apps are not equal. Not only is the app source not equal, but 9 out of 10 times, the way the apps behave isn’t the same either.
There are no cross platform selectors. Correct! I hear this comment primarily from people who are used to automating with Selenium. I’ll address more on this point later.
Appium tests are slow. Correct again! Appium tests can be 3-6 times slower than desktop.
Let’s explore why.
Automating Native Apps
A lot of people use their Selenium knowledge to automate native apps. I don’t think it’s a wrong approach, because if we look at a responsive web app, we can almost always use the same script and selectors on desktop and mobile. They have the same source (the DOM), and are interpreted the same for every browser on desktop Chrome, Firefox, Safari, Internet Explorer, Microsoft Edge, but even on mobile Safari and mobile Chrome.
However, I was not referring to web apps. I also see that a lot of people use their Selenium knowledge on native apps and get into trouble. This mainly has to do with the app source of native apps, so let’s take a look at the native app source, the UI Hierarchy, for an iOS app. This can easily be visualized with Appium Desktop.
On the left you see the visualization of the app and in the middle you see the UI hierarchy. This tree is not HTML, but XML, and as you can see—it’s a very large tree. The reason for this is that all elements can be found in this tree, even the elements that you don’t see on your screen, such as the menu. This looks like the same behavior as we have seen with HTML.
Now let’s take a look at Android.
Here you see the UI hierarchy that Appium sees, which is completely different in comparison to iOS. You don’t have HTML here, but also an XML tree. What you might also see is that Android will only give us back the elements that are shown on the screen. This is, next to different element names, already a big difference between iOS and Android.
So iOS has all elements in the view, but Android only the elements that are in the viewport. And as I mentioned earlier, people find it hard to find a cross platform selector, which I can imagine with these different UI hierarchies. Do you now see why it’s harder to use your existing Selenium knowledge to interact with an iOS and Android app?
The No-XML Secret
As I said at the beginning of this post, I wanted to let you in on a little secret. Are you ready?
There is no XML. iOS and Android don’t have a UI hierarchy in XML.
Shocking, isn’t it? Well, I’m going to explain it to you. Both iOS and Android work with views, and the views are translated by Appium to XML. Android provides a useful dumpWindowHierarchy which gives back XML and makes the translation from Views to XML pretty easy and pretty fast.
XPATH and XML are not native languages for iOS. Appium needs to perform some magic with the app hierarchy. It must be recursively walked and serialized into XML. This by itself can take a lot of time, especially if your app has many elements. Then, once the XPath query has been run on this XML serialization, the list of matching elements must be deserialized into actual element objects before their WebDriver representations are returned to your client call. This translation is only done when we:
Ask for the source, like with Appium Desktop when we want to walk through the source of the app
Use an XPATH selector
This is one of the reasons that for example iOS is twice as slow as Android when using XML. So how can we fix that?
That brings us to something very important, the locator strategy.
Below is a list of locator strategies that you can use for native apps. It’s in my favorite order based on speed. You’ll note XPATH is last, despite being used most often, and I’ll explain why.
An accessibility label in an iOS or Android app is a string that will tell a screen reader what the function of an element on the screen is.
So why should you use accessibilityIDs? Well, there are numerous reasons, but the most important ones are these:
They are already indexed, and that makes it much faster than XPATH, because they are directly queried on the views.
They are cross-platform. (So you now have an answer on how to create a cross-platform locator strategy)
In some countries, you can even be fined if you don’t have them.
iOS predicate string
A different way of selecting elements can be done with iOS predicate strings.
This is something that is already built in XCUITEST and queries the attributes on an element like name, value, label, type and visible. One of the advantages of the iOS predicate string is that it is really fast.
iOS class chain
But next to the iOS predicate string there is also a way of querying some elements from parent to child. This can be compared with XPATH, but XPATH is more powerful in this due to the fact that it can query elements from child to parent. But as I said, this will trigger generating XML which makes finding elements take longer. So here you need to think about a good balance between costs and wins.
This one is simple, it’s just the class name, but with so many elements you might ask yourself if this will give you a unique element.
XPATH, although it tends to be everybody’s favorite, is brittle and slow. I think, based on the points above, you can already draw your own conclusion why.
Finally, by now you should know that both iOS and Android don’t work with XML and each time you use XPATH, Appium first needs to translate the UI-view into XML which takes time. Android is faster than iOS simply because it doesn’t render all elements, only the element in the view. Thus regardless of platform, using XPATH leads to slower tests.
If you’d like to see the real numbers and comparison of all these locator strategies check out my Tech Talk: How to speed up your native Appium iOS tests by almost 50%, where I demo of each one of these on a sample app. Happy testing!