Wednesday 30 June 2021

Python Appium - Difference between Implicit wait and Explicit wait

 Why we need to use wait?

We need to use the wait mechanism because the webdriver is quite faster than the Page load. Sometime it reaches to page and on webpage few of the elements are not loaded fully. In short DOM takes time to load all the elements on screen and this may lead webdriver does not found the element which will raise ElementNotVisible exception.

The main idea behind using waits in our script is to keep webdriver and page in sync by providing some delays between element identification and action performed.

There are two types of waits that are available with webdriver object

            1. Implicit wait

            2. Explicit wait

Let us see above two waits with real time examples

1. Implicit wait:

Implicit wait tells webdriver object to wait for certain amount of time i.e. whatever we have mentioned in the method. The implicit wait once set, it would be set for the entire life of driver object for that particular session. For example we have defined a implicit wait for 5 secs and DOM takes to load the element for 6 secs then it would raise an exception as ElementNotVisible. Suppose the DOM took 3 secs to load the element then implicit wait would be only 3 secs and would continue with further execution. This is the best way to reduce the time to identify the element on page. The custom method time.sleep(5) would wait of irrespective of whether element is found or not. This may result in slow execution. So its always preferable to use implicit wait rather than using time.sleep() method. There are some cons using implicit wait in your code,

1. The performance issues may be escaped and would never be catch using your script

2. The execution becomes little slower as implicit wait is introduced.

def test_calculator_click_number():
desired_caps = {
'platformName': 'android',
'udid': 'emulator-5554',
'deviceName': 'Pixel API 24',
'platformVersion': '7.0',
'appPackage': 'com.android.calculator2',
'appActivity': 'com.android.calculator2.Calculator',
'systemPort': 8201
}
driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps)
driver.implicitly_wait(5)
log = BaseClass().get_logger()
log.info("-------------- Click number on calculator app --------------")
cal = Calculator(driver)
cal.click_number(9)
log.info("-------------- Click number on calculator app test is completed --------------")

So in above example, driver object would wait for 5 or less than 5 second  to identify the element on page. This would be happening for each statement it goes through the script.

2. Explicit wait:

Once defined explicit wait, the wait is applied only for specific element which takes longer time to load.

Explicit wait is also similar to implicit wait, for example if wait is defined as 5 secs and element is found in 3 seconds then would continue next line of code. This does not make your execution slower which is found in implicit wait. Explicit wait is little complicated to implement than implicit wait because here we have to find the element first on which explicit wait has to be applied and later have to add in the script.

def __init__(self, driver):
self.driver = driver
self.formula = WebDriverWait(self.driver, 5).until(
e.visibility_of_element_located((
MobileBy.ID, "com.android.calculator2:id/formula")))
self.result = WebDriverWait(self.driver, 5).until(
e.visibility_of_element_located((
MobileBy.ID, "com.android.calculator2:id/result")))
self.divide_button = WebDriverWait(self.driver, 5).until(
e.visibility_of_element_located((
MobileBy.ID, "com.android.calculator2:id/op_div")))
self.multiply_button = WebDriverWait(self.driver, 5).until(
e.visibility_of_element_located((
MobileBy.ID, "com.android.calculator2:id/op_mul")))
self.minus_button = WebDriverWait(self.driver, 5).until(
e.visibility_of_element_located((
MobileBy.ID, "com.android.calculator2:id/op_sub")))
self.plus_button = WebDriverWait(self.driver, 5).until(
e.visibility_of_element_located((
MobileBy.ID, "com.android.calculator2:id/op_add")))
self.equals_button = WebDriverWait(self.driver, 5).until(
e.visibility_of_element_located((
MobileBy.ID, "com.android.calculator2:id/eq")))
self.delete_button = WebDriverWait(self.driver, 5).until(
e.visibility_of_element_located((
MobileBy.ID, "com.android.calculator2:id/del")))

Tuesday 22 June 2021

Mobile Application Testing: Python Appium - How to automate gestures - Tap, lo...

Mobile Application Testing: Python Appium - How to automate gestures - Tap, lo...: So above gestures are the part of TouchAction class of appium. So let us go in details of this class TouchActions: TouchAction objects conta...

Tuesday 1 June 2021

Python Appium - Locating elements using xpath,class,accessibility ID,ID and Image

 Appium Locators

There are five locators which are extensively used for identifying mobile element using appium inspector. So let us see each with examples.

You can also check

ID

This can be used when you know the id attribute of an element. If the element is not found by mentioned attribute, it would raise an exception "NoSuchElementException"

So let us take example of dialer page. Here we have launched dialer screen using below desired capabilities
desired_caps = {
'platformName': 'android',
'udid': 'emulator-5554',
'deviceName': 'Pixel 1 API 28',
'platformVersion': '9.0',
'appPackage': 'com.google.android.dialer',
'appActivity': 'com.google.android.dialer.extensions.GoogleDialtactsActivity'

}
In above yellow marked item was identified by any of the locators so I have decided to go by co ordinate method. Third option given appium inspector is 'Tap By Co-ordinates'. For co ordinates, first click on recording and click on the dialpad item. you would see auto generated code for it as below
You can include above code in your automation script as below
from appium.webdriver.common.touch_action import TouchAction
'''Tap on dialer pad, as we could not see any valid element identifiers'''
touch = TouchAction(driver)
touch.tap(x=955, y=1515).perform()
So I have selected python language here, you can select any other language in which you are writing your automation scripts. Copy paste python code in your script. On this page let us click on dial for id attribute
Let us check whether we have found a unique identifier. On appium inspector there is an option on top beside recording option called 'Search for Element'.


So once it is validated here, you can include it in your code as below
driver.find_element_by_id("com.google.android.dialer:id/digits")
You need to type some number on the element you have identified for this you can use send_keys() method.
driver.find_element_by_id("com.google.android.dialer:id/digits").send_keys("810000000")
Complete code would look like as below
import pytest
from appium import webdriver
from time import sleep
from appium.webdriver.common.touch_action import TouchAction

def __init__(self, driver):
self.driver = driver

def test_locators():
desired_caps = {
'platformName': 'android',
'udid': 'emulator-5554',
'deviceName': 'Pixel 1 API 28',
'platformVersion': '9.0',
'appPackage': 'com.google.android.dialer',
'appActivity': 'com.google.android.dialer.extensions.GoogleDialtactsActivity'

}
driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps)

'''Locate Element by ID'''
'''Tap on dialer pad, as we could not see any valid element identifiers'''
touch = TouchAction(driver)
touch.tap(x=955, y=1515).perform()
driver.find_element_by_id("com.google.android.dialer:id/digits").send_keys("810000000")
print("\n Element by ID is found")
To execute run below command,
py.test test_locators.py -v -s
Classname
This can be used when you know the classname attribute of an element. If the element is not found by mentioned attribute, it would raise an exception "NoSuchElementException"

Let us take example of calculator native app. The desired capabilities would be like as below
desired_caps = {
'platformName': 'android',
'udid': 'emulator-5554',
'deviceName': 'Pixel 1 API 28',
'platformVersion': '9.0',
'appPackage': 'com.android.calculator2',
'appActivity': 'com.android.calculator2.Calculator'

}
driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps)
Code snippet for identify element by class name would be as below
'''Locate Element by Class'''
driver.find_element_by_class_name("android.widget.ImageButton")
print("Class Element is found")


Accessibility ID:
This can be used when you know the accessibility id attribute of an element. If the element is not found by mentioned attribute, it would raise an exception "NoSuchElementException"

Let us take example of flipkart app for this.

The code would look like as below,
desired_caps = {
'platformName': 'android',
'udid': 'emulator-5554',
'deviceName': 'Pixel 1 API 28',
'platformVersion': '9.0',
'noReset': 'true',
'appPackage': 'com.flipkart.android',
'appActivity': 'com.flipkart.android.activity.HomeFragmentHolderActivity'

}
driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps)
time.sleep(20)
'''Locate Element by Accessibility ID'''
driver.find_element_by_accessibility_id("Flipkart home")
print("Element found")
Xpath
This can be used when you know the xpath attribute of an element. If the element is not found by mentioned attribute, it would raise an exception "NoSuchElementException"

The code would look like as below,
desired_caps = {
'platformName': 'android',
'udid': 'emulator-5554',
'deviceName': 'Pixel 1 API 28',
'platformVersion': '9.0',
'noReset': 'true',
'appPackage': 'com.flipkart.android',
'appActivity': 'com.flipkart.android.activity.HomeFragmentHolderActivity'

}
driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps)
time.sleep(20)
'''Locate Element by Xpath'''
driver.find_element_by_xpath("//android.widget.ImageView[@content-desc='Flipkart home']")
print("Element found by xpath")

Image:
This can be used when you know the image attribute of an element. If the element is not found by mentioned attribute, it would raise an exception "NoSuchElementException"
desired_caps = {
'platformName': 'android',
'udid': 'emulator-5554',
'deviceName': 'Pixel 1 API 28',
'platformVersion': '9.0',
'noReset': 'true',
'appPackage': 'com.flipkart.android',
'appActivity': 'com.flipkart.android.activity.HomeFragmentHolderActivity'

}
driver = webdriver.Remote("http://localhost:4723/wd/hub", desired_caps)
time.sleep(20)
'''Locate Element by Image'''
driver.find_element_by_image('c://sample/2021/to/img.png')
print("Element found by Image")


Feature Posts

Python Appium - Step by step procedure for capturing screenshot

 Why To capture screenshot? It is as important as your logs. If there is any failure for any test scenario, we can provide screenshot for th...