Tool Overview for Element Detection
Appium provides several built-in tools for element identification:
- Appium Inspector: Built-in component for element detection
- UI Automator: Android SDK's native tool for element analysis
Core Concept of Element Location
Element location represents a critical component in mobile automation testing, similar to web automation. Precise element identification enables subsequent operations like input, clicks, swipes, and drag actions. Appium offers multiple location methods including ID-based, name-based, class-based, hierarchical, relative positioning, XPath, H5 element detection, and UI Automator approaches.
Available Location Methods
- ID-based location
- Name-based location
- Class-based location
- List-based location
- Relative location
- XPath location
- H5 page element location
- UI Automator location
ID-Based Element Location
Similar to unique identification numbers in real life, each UI element can have a distinct ID value for differentiation. Appium uses the find_element_by_id() method for ID-based location.
Test Scenario Example
- Install kaoyan3.1.0.apk
- Click the cancel button on upgrade screen
- Click skip button on guide page
from appium import webdriver
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['deviceName'] = '127.0.0.1:62025'
desired_caps['platformVersion'] = '5.1.1'
desired_caps['app'] = r'C:\Users\Desktop\kaoyan3.1.0.apk'
desired_caps['appPackage'] = 'com.tal.kaoyan'
desired_caps['appActivity'] = 'com.tal.kaoyan.ui.activity.SplashActivity'
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
driver.implicitly_wait(5)
driver.find_element_by_id('android:id/button2').click()
driver.find_element_by_id('com.tal.kaoyan:id/tv_skip').click()
Handling Conditional Elements
When dealing with optional UI elements (like update popups that may not appear), two primary approaches exist:
Approach 1 - Exception Handling
The most effective method involves catching NoSuchElementException exceptions:
from appium import webdriver
from selenium.common.exceptions import NoSuchElementException
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['deviceName'] = '127.0.0.1:62025'
desired_caps['platformVersion'] = '5.1.1'
desired_caps['app'] = r'C:\Users\Desktop\kaoyan3.1.0.apk'
desired_caps['appPackage'] = 'com.tal.kaoyan'
desired_caps['appActivity'] = 'com.tal.kaoyan.ui.activity.SplashActivity'
desired_caps['noReset'] = 'True'
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
driver.implicitly_wait(5)
def verify_cancel_button():
try:
cancel_element = driver.find_element_by_id('android:id/button2')
cancel_element.click()
except NoSuchElementException:
print('Cancel button not found')
def verify_skip_button():
try:
skip_element = driver.find_element_by_id('com.tal.kaoyan:id/tv_skip')
skip_element.click()
except NoSuchElementException:
print('Skip button not found')
verify_cancel_button()
verify_skip_button()
Complete Login Implementation Using ID Location
Requirements Analysis
For Chinese text input, configure these capabilities:
desired_caps['unicodeKeyboard'] = "True"
desired_caps['resetKeyboard'] = "True"
Implementation Code
from find_element.capability import driver, NoSuchElementException
def execute_login():
driver.find_element_by_id('com.tal.kaoyan:id/login_email_edittext').clear()
driver.find_element_by_id('com.tal.kaoyan:id/login_email_edittext').send_keys('selfstudy2018')
driver.find_element_by_id('com.tal.kaoyan:id/login_password_edittext').send_keys('password2018')
driver.find_element_by_id('com.tal.kaoyan:id/login_login_btn').click()
try:
driver.find_element_by_id('com.tal.kaoyan:id/mainactivity_button_mysefl')
except NoSuchElementException:
execute_login()
else:
driver.find_element_by_id('com.tal.kaoyan:id/mainactivity_button_mysefl').click()
driver.find_element_by_id('com.tal.kaoyan:id/activity_usercenter_username').click()
execute_login()
Name-Based Location
For Android applications, name location corresponds to the text attribute. Usage example:
from find_element.capability import *
driver.find_element_by_name('Enter username').send_keys('selfstudy2017')
driver.find_element_by_name('Login').click()
Note: This method has been deprecated since Apppium 1.5 due to text attribute instability.
Class Name Location
Class-based location identifies elements by their type. However, many elements share identical clas names, making precise targeting challenging. For instance, both username and password fields might have the same class name: "android.widget.EditText", allowing only the first element to be targeted.
from find_element.capability import driver
driver.find_element_by_class_name('android.widget.EditText').send_keys('selfstudy2018')
driver.find_element_by_class_name('android.widget.EditText').send_keys('password2018')
driver.find_element_by_class_name('android.widget.Button').click()
Relative Location Strategy
Relative location finds a parent element with specific attributes first, then locates child elements based on that parent.
Implementation Example
from find_element.capability import driver
driver.find_element_by_id('com.tal.kaoyan:id/login_register_text').click()
parent_element = driver.find_element_by_id('com.tal.kaoyan:id/activity_register_parentlayout')
parent_element.find_element_by_class_name('android.widget.ImageView').click()
XPath Location
XPath relies on absolute or relative paths and element attributes. While absolute XPath paths have lower execution efficiency, relative paths and attribute-based selection are more practical.
XPath Exprestion Reference
| Expression | Description |
|---|---|
| / | Select from root node |
| // | Select nodes regardless of position |
| nodename | Select all child nodes |
| . | Select current node |
| .. | Select parent node |
| @ | Select attributes |
Practical Example
from find_element.capability import driver
driver.find_element_by_xpath('//android.widget.EditText[@text="Enter username"]').send_keys('testuser123')
driver.find_element_by_xpath('//*[@class="android.widget.EditText" and @index="3"]').send_keys('securepassword')
driver.find_element_by_xpath('//android.widget.Button').click()
List-Based Element Location
When multiple elements share the same class attribute, use list location to differentiate them:
from find_element.capability import driver
driver.find_element_by_id('com.tal.kaoyan:id/login_register_text').click()
driver.find_element_by_id('com.tal.kaoyan:id/activity_register_userheader').click()
image_list = driver.find_elements_by_id('com.tal.kaoyan:id/item_image')
image_list[10].click()
driver.find_element_by_id('com.tal.kaoyan:id/save').click()
Comprehensive Registration Implementation Using List Location
Complete Registration Flow
from find_element.capability import driver
import random
driver.find_element_by_id('com.tal.kaoyan:id/login_register_text').click()
driver.find_element_by_id('com.tal.kaoyan:id/activity_register_userheader').click()
image_collection = driver.find_elements_by_id('com.tal.kaoyan:id/item_image')
image_collection[10].click()
driver.find_element_by_id('com.tal.kaoyan:id/save').click()
# Generate unique registration data
username_value = 'user2018' + 'AUTO' + str(random.randint(1000, 9000))
password_value = 'pass' + str(random.randint(1000, 9000))
email_value = 'test' + str(random.randint(1000, 9000)) + '@gmail.com'
print('Username: %s' % username_value)
print('Password: %s' % password_value)
print('Email: %s' % email_value)
# Fill registration form
driver.find_element_by_id('com.tal.kaoyan:id/activity_register_username_edittext').send_keys(username_value)
driver.find_element_by_id('com.tal.kaoyan:id/activity_register_password_edittext').send_keys(password_value)
driver.find_element_by_id('com.tal.kaoyan:id/activity_register_email_edittext').send_keys(email_value)
driver.find_element_by_id('com.tal.kaoyan:id/activity_register_register_btn').click()
# School selection flow
driver.find_element_by_id('com.tal.kaoyan:id/perfectinfomation_edit_school_name').click()
driver.find_elements_by_id('com.tal.kaoyan:id/more_forum_title')[1].click() # Province selection
driver.find_elements_by_id('com.tal.kaoyan:id/university_search_item_name')[1].click() # University selection
# Major selection flow
driver.find_element_by_id('com.tal.kaoyan:id/activity_perfectinfomation_major').click()
driver.find_elements_by_id('com.tal.kaoyan:id/major_subject_title')[1].click() # Subject
driver.find_elements_by_id('com.tal.kaoyan:id/major_group_title')[2].click() # Group
driver.find_elements_by_id('com.tal.kaoyan:id/major_search_item_name')[1].click() # Specific major
driver.find_element_by_id('com.tal.kaoyan:id/activity_perfectinfomation_goBtn').click()
Important: Set noReset capability to 'False' before running to avoid interference from previous registration data.
Common Error Resolution
Element Not Found Error
selenium.common.exceptions.NoSuchElementException: Message: An element could not be located on the page using the given search parameters.
Solution: Verify the accuracy of the element identifier values.