How to wait for new element with same name as visible one to appear on screen?

We’re using Appium with iOS Simulator and test functions written in Java.

We have an iOS App with screen 1 containing a UICollection view, and tell Appium to click on one of its elements.

This opens screen 2 (and the scrolling animation takes about 500 ms), which also contains an UICollection view. I want to find out the size of the UICollection view of the second screen with Appium.

The problem is that Appium is too fast and executes the findElements() method directly after the click, which causes it to find the UICollection view of the first screen.


webDriver.findElements( By.className( "UIACollectionCell" ) ).size();
// is supposed to find the UICollection view on the second screen,
// but actually finds the UICollection view on the first screen
Appium provides several waiting functions. However as far as I can see all of them are intended to be used in this fashion: "wait until element at location X / with name X becomes visible"

If I try to use these waiting functions, they don’t wait at all because they immediately find the UICollection view of the first screen, which has the same location and name as the one on the second screen.

The only solution I have found is to use Thread.sleep:

webDriver.findElements( By.className( "UIACollectionCell" ) ).size();

But we don’t want to use Thread.sleep in code that will run on the client’s server on hundreds of tests.

We might be able to modify the App and enter metadata into the views so that Appium is able to distinguish them, but this situation occurs in several places and the App is being programmed by the client, so we want to avoid this too.

What is a simple and safe way to wait for the new screen to appear, without modifying the code of the iOS App?

I have also posted this question on StackOverflow:

The only answer suggests a rather ugly workaround by calling a wait on an item that doesn’t exist, then after the timeout, continuing. Is this really the only way?

There is nothing specific to the second screen that you can search after the click and once you find it, then do your size query?

Yes that’s possible. But I think this is also a workaround with drawbacks. Now we rely on that other completely unrelated UI element just to be able to find the UI element we’re looking for. If the other unrelated UI element gets changed the code breaks. And this problem occurs in several places, not just in the case of the UICollection view. What if the UI is supposed to do an in-place replacement of a single element on the screen while the rest of the screen stays the same - how do you find the new element? The only method I see is to use the “waste time by waiting for nonexisting element, then look for new element” workaround.

I dont agree with your point of view! If an old device takes 10 seconds to change pages, how will appium now if its suppose to find element now or in 10 seconds time?

The way I do my tests its to have a wait before every findElement in order to avoid that problem. In the case I have same element on both pages, then I look for something unique in new page. This wont delay your tests and will make sure you do not get errors that are from tests and not from app.

If you want to stick to that approach. If they have different path/parents/childs you can use XPath, maybe?

You’re right that any hard-coded delay may sometimes not be enough, or it is set so high that the delay becomes annoying.

The XPaths are exactly the same in the given example.

Looking for something else unique on the new screen, then finding the desired element, is probably the way to go. Thanks for your help.