Monday, September 23, 2019

Test Synchronisation in Appium | Mobile Automation

Test Synchronisation in Appium | Mobile Automation



Most of the time test script will because of application takes to load the web page due to this element will not be loaded to perform the actions specified in the script. If two or more components are working together in parallel at the same pace or rate, synchronisation comes into play.

We see it in almost every application whenever the screen changes it takes a few milliseconds (or seconds) to load, and if you do not manage the proper synchronisation in your code then you might face the dreaded “ElementNotVisibleException” or “NoSuchElementException” exceptions. This is because the screen hasn’t finished loading and is not synchronised with your test code. That is, your test code is over eager and starts trying to perform an action on an element that hasn’t been loaded yet. To avoid this we need to implement proper synchronisation in our automation script.

Broadly there are two types synchronisation:


1) Unconditional synchronisation,
2) Conditional synchronisation

Now let’s discuss each of them in detail.


1) Unconditional synchronisation:


Unconditional Synchronisation is also known as Static Synchronization or Static Wait.
As the name suggests, it specifies a particular fixed (static) time to wait before starting the execution. Here Appium(or any program) will wait the specified amount of time and then it will resume the execution. During this wait, it will not perform any action, that is big drawback of this unconditional synchronisation.

Sometimes you put this wait  with 10 seconds to make sure element get displayed, if element loaded and displayed within 2 seconds also still it waits for 10 seconds. Due to this our automation script execution may take longer.

The standard example of Unconditional Synchronisation is below:
try{

Thread.sleep(5000);

  } catch(InterruptedException e) 
    {
   System.out.println( e);
    }




Here the Thread.sleep(5000) function would take 5000 ms to execute.
Key to note is that this wait will be absolute, even if the underlying condition you were waiting on has been met. For example, you may put in a wait for 3 seconds waiting for the screen to load. Even if that screen loads in 2 seconds, the system will still wait for the additional second. The converse is also true - Sometimes the wait finishes before the underlying operation and execution proceeds. 

  In test automation, for example, limited network connectivity may slow the mobile application response time and a screen change may now take 5 seconds while the script only waits 3 seconds. Due to this, we will face “ElementNotVisibleException” or “NoSuchElementException” exceptions.
So unconditional synchronisation or static wait is not the preferred way to deal with dynamic responses.

However it is a viable strategy to use it when you are working with some 3rd party interfaces and where you can not identify the underlying condition you need to wait on OR you are sure about the response time.


2) Conditional synchronisation:


Conditional synchronization depends on some underlying condition. So in addition to a specified absolute time to wait, the condition is also passed into the method. Here the script(or program) will resume execution as soon as the condition is met - or, in the event the condition isn’t met, it will resume after the specified time.

Appium provides 3 types of conditional synchronisation.

  1. Implicit wait
  2. Explicit wait
  3. Fluent wait



1) Implicit wait:


Implicit wait tells the Appium’s webdriver object to poll the DOM for the specified amount of time while trying to find the element before throwing an “ElementNotVisibleException” or “NoSuchElementException” exceptions.
The big advantage of using Implicit wait is it’s lifespan. As we apply Implicit wait on the Webdriver object, it will be valid for the webdriver object’s lifespan.

Below is the code to apply the Implicit wait of 10 seconds on the Webdriver object.

//Define AppiumDriver
AppiumDriver driver = new AppiumDriver(new URL(APPIUM_SERVER_URL), capabilities);
//Set implicit wait upon AppiumDriver
Driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);



NOTE: Ideally you should set the implicit wait as soon as you initialize the WebDriver.
Please remember that Implicit wait works with only driver.findElement() and driver.findElements()  methods - it won’t work for other methods.

Let’s look at a simple example for better understanding.
You want to click on the Login button on the home screen but the home screen itself takes some to appear when the Appium script runs.
So ideally you need to specify a condition that Appium should locate the Login Button element(on the home screen) within 10 seconds after starting the script and if the element is not present (or the home screen has not appeared) after 10 seconds, only then throw Exceptions.
You can write the following statement after writing the above (webdriver initialization and set implicit wait of 10 sec.) code:
You will notice that we don’t need to specify anything else to the code as we already added the 10 seconds implicit wait to the AppiumDriver object. Now
it will be polling the DOM for 10 seconds until the Login Button is found and as soon as the button is found, it will be clicked.

However there are a few limitations to using Implicit wait:
  1. As you know it’s only useful for driver.findElement() and driver.findElements() methods - we can’t check other
conditions. For example if you want to wait until a particular button is displayed on the screen as well as on the DOM, you can’t check it with Implicit wait. There is a chance that the particular button is in the DOM but it’s hidden or it’s not visible on the screen, so in that case Implicit wait executes successfully but would not give us the accurate answer about the element’s visibility.
  1. There is a chance that the time for the implicit wait isn’t enough. For example as we mentioned earlier where we’re waiting 5 seconds but limited network connectivity causes the screen to take 10 seconds to load. In that case Implicit wait will break.


2) Explicit wait:


driver.findElement() &  driver.findElements() - These limitations are resolved by the Explicit wait.

Explicit waits are the best synchronization methods for dynamic responses in the application.

Explicit wait informs the AppiumDriver to wait
  1.  Until the specified condition is met OR
  2. The specified time has elapsed


...before throwing the “ElementNotVisibleException” or “NoSuchElementException” exceptions.

And if the AppiumDriver is able to meet the condition within the specified amount of time then the code will get executed.
In explicit wait we need to tell the WebDriver object to wait for a specific condition using the ExpectedConditions class. So, actually this wait is specific to a particular single element rather than the whole WebDriver object (unlike implicit wait).
The WebDriverWait class will call the ExpectedCondition every 500 milliseconds by default until the output is True. So if you have given 10 seconds of timeout, ExpectedCondition would be called 20 times at 500 milliseconds intervals to check if the condition has been met.

Now let’s take one simple example to understand the use of Explicit wait.
In almost all mobile applications when you perform a Login it takes some time to load the dashboard or home screen and its elements. For example purposes, let’s say there is a menu button on the dashboard screen. You can use an Explicit wait with the condition of wait till menu button element is visible:


(ExpectedCondtions.visibilityOf(<menu_button_element>)) on Dashboard screen.
When we initialize new object of WebDriverWait class, we need to pass 2 parameters:


  1. WebDriver object.
  2. Number of seconds



There are many conditions are defined in ExpectedConditions class, but we can list down a few popular one’s:

Condition Name
Purpose
elementToBeClickable(By locator)
Example:
ExpectedConditions.elementToBeCli ckable(By.id(“loginButton”));
An expectation for checking an element is visible and enabled such that you can click it.
In this method you need to pass the object of By class.
elementToBeClickable(WebElement element)
Example:
ExpectedConditions.elementToBeCli ckable(driver.findElement(By.id("me nubutton")));
An expectation for checking an element is visible and enabled such that you can click it. In this method you need to pass the object of WebElement class.
presenceOfElementLocated(By locator) An expectation for checking that an element is present on the DOM of a page. This does not necessarily mean that the element is visible.
visibilityOfElementLocated(By locator) An expectation for checking that an element is either invisible or not present on the DOM.
elementToBeSelected(WebElement element) An expectation for checking if the given element is selected.
numberOfElementsToBe(By locator, java.lang.Integer number) An expectation for checking number of WebElements with given locator.
titleIs(java.lang.String title)
An expectation for checking the title of a page.
This is not applicable to Appium Mobile Application.
textToBePresentInElement(WebEle ment element, java.lang.String text) An expectation for checking if the given text is present in the specified element.



3) Fluent wait:

Fluent wait is part of WebDriverWait, The only difference is it’s more configurable than Explicit wait.
You can configure the:
1.     1)  Pollfrequency : The is the Time Interval to check whether the expected condition for the webelement is met or not. So if poll frequency is 1 second and total wait time is 10 seconds, fluent will check if the condition is met or not at every 1 second for a maximum of 10 times.
2.     2)  IgnoretheException : If you want to ignore a specific exception such as NoSuchElementExceptions while searching for an element.
3.     3)  Maximumwaittime : The total maximum amount of time to wait for a condition is met before throwing an exception.


Below is the example of Fluent wait:


FluentWait<AppiumDriver>  wait = new FluentWait<AppiumDriver>(driver);
wait.pollingEvery(Duration.ofSeconds(1));
wait.ignoring(NoSuchElementException.class);
wait.withTimeout(Duration.ofSeconds(10));



Which types of Wait you should use When?



Wait Type
Purpose
Implicit
When you need to apply common wait without any condition.
Explicit
When you need to test expected condition for an element
Fluent
When you need to test expected condition for an element after a specific amount of time every x seconds/minutes


No comments:

Post a Comment

If any suggestions or issue, please provide