Creating Accessibility IDs for a Hybrid App


#1

I am working on a small QA team that has been tasked with automating my company’s mobile app. The app is a hybrid app written in Javascript with the Cordova framework, and the app does not have ID’s for 9/10 of its elements when inspected in Appium. However much I would love to research this on my own and not bother you for an answer, I am currently not finding a whole lot of information online on what exactly a developer needs to do to ensure each element has a working accessibility ID compatible with automation.

So my question is, how are accessibility ID’s added to a Hybrid app?

I have made an attempt at answering this question myself, but when I search “Accessibility ID Android” it almost appears as if they don’t exist outside the context of automation. Does that mean that this is something I should be doing myself, and not the developer? The closest answer I found was some vague info on the Xamarin forums about a setting ContentDescriptor using XML, but it was in no way instructional and I am unable to find a tutorial on this and I’m not sure whether or not it is the answer I am looking for. Even if I knew how to set this up in XML, I have no direct access to the app itself, and so if that is a requirement for this method I would need to provide the developer with enough information to make the changes himself.

How is setting up accessibility app different from setting up regular IDs? Are there best practices in place to ensure the IDs won’t cause problems? Is this a job for the developer or for QA? Are there special exceptions for a Hybrid App?


#2

If the app is hybrid then the automation should run in the web context as well. Which means that identifiers will be interpreted in the same way as for a normal web page. The way these web identifiers are mapped to native context is up to the used framework (react/cordova etc.) and the operating system to decide and usually developers have not much control over it.


#3

Adding to what mykola said… I think you are having trouble finding information online because of the term “Accessibility ID” which doesnt really apply to hybrid apps like Cordova and the web context DOM. My understanding is that the term really only applies to native app development. Element IDs are optional in the HTML world which would explain your app not having very many. If you cant get your development team to add some to aid your automation effort, can you access the elements you are looking for by different means? XPath is a very powerful tool in this regard because you can select elements based on class name, inner text, element type, and sibling hierarchy (etc… etc…)


#4

That explains a lot. In that case I will ask the developer to add regular IDs then. It really shouldn’t matter how he creates them so long as they are unique, correct? I would use xpath, but have heard that ID is preferred less likely to change over time which would mean less maintenance. According to my research ID’s are somewhat split between resource-ID and “name” in android and ios. For a hybrid app will it just be a plain ID? Does Appium prefer this IDs to be done any certain way? I know resource-id’s need package info while writing a script.

@mykola Thank you, I have heard and will be running in the web context.


#5

For a hybrid app that has a UI written in HTML, yes it is just ID. The resource ID + name scheme is for native stuff. We almost exclusively use XPath to find elements in my shop because it is flexible and can be used to find elements by any attribute, ID included. I also operate under the assumption that element IDs will change every time the UI loads because that is how a lot of modern day JavaScript frameworks operate…

These days, HTML elements change all the time and a JavaScript framework update that decides to use underscores in the place of dashes all of a sudden can wreck your automation… Dont aim for less maintenance thinking you will do less work; go for easy and painless maintenance that lets you react to changes quickly because its sure to happen at the worst possible time

I should point out that Appium itself doesnt prefer anything in regards to how you select elements… Think of Appium as the thing that connects your automated testing (selenium, testng, etc) and your app. I use Selenium in Java so that is what my few following examples are in:

driver.findElement(By.xpath( “//div[@class=‘x-clear-icon’]”))

driver.findElement(By.xpath("//div[contains(@id,‘ext-foo_text-’)]")) /// Id only has to contain that text not equal it

driver.findElement(By.xpath("//div[text()=’" + User1 + “’]”)) // Inner Text of the div

driver.findElement(By.xpath("//input[@placeholder=‘Select Assignee’]"))


#6

Okay, I have had success with this and can now tap any element on the phone by coordinate. I wasn’t able to get click to work in the web context, but I think this behavior is expected, is that correct? I tried clicking in the web context, and I tried storing the element as a variable then clicking it in native context but that didn’t work either.


I used the method described in this article under “Touch Actions”, which is a lot slower than using a click. Is this what you use for clicking elements? If there aren’t any better options I can use this, but having a different offset for every phone is inconvenient and the method is slow.

Thanks so much for your help!


#7

Glad to hear you are making progress! I actually have the same issue as you do with our hybrid framework, ExtJS. Some of these frameworks play around with the default click action to make it act more like a native app and it interferes with the way automation performs a click. I solved it in the same way you are describing in that write up which was to switch to the native context and “tap” at the coordinates needed. It took me quite a while to figure that out myself so good work there. I have not found a better solution than that…

When you say it is slow, do you mean it is slow at runtime or slow to implement? I found that it is somewhat slow to run but not unacceptable. I wrapped my native tap in a global method that takes an element to tap and it handles any phone size so its not a big deal to use it over and over again