我们知道,UI 自动化测试最基本的功能就是如何定位元素并进行接下来的点击、输入、验证等操作;
从另一角度来看,UI 自动化测试用例是否稳定,关键也要看你的元素定位是否合理。下面总结一下在日常使用 selenium 进行元素定位的问题。
selenium 中提供的元素定位方式,大概有以下几种:
方法如下:
def find_element(self, by=By.ID, value=None):
"""
Find an element given a By strategy and locator. Prefer the find_element_by_* methods when
possible.
:Usage:
element = driver.find_element(By.ID, 'foo')
:rtype: WebElement
"""
即通过某种定位方式(如 id、name、css、xpath 等)和对应的 value 值来查找某个元素。
引申的方法:
find_element_by_id(id):
# 等同于 self.find_element(by=By.ID, value=id_)
find_element_by_xpath(self, xpath):
# 等同于 self.find_element(by=By.XPATH, value=xpath)
这种定位方式的使用场景:元素具备一个唯一的属性,可以通过该属性进行定位。如唯一的 id 、xpath、css 等。
页面中一般不会出现每一个元素都存在唯一的 id 等属性,所以无法通过唯一属性定位该元素。此时,selenium 提供了定位多个元素的方法。
方法如下:
def find_elements(self, by=By.ID, value=None):
"""
Find elements given a By strategy and locator. Prefer the find_elements_by_* methods when
possible.
:Usage:
elements = driver.find_elements(By.CLASS_NAME, 'foo')
:rtype: list of WebElement
"""
当多个元素都具备相同的属性时,可以通过这个方法查找到一个元素数组。
引申的方法:
def find_elements_by_id(self, id_):
"""
Finds multiple elements by id.
:Args:
- id\_ - The id of the elements to be found.
:Returns:
- list of WebElement - a list with elements if any was found. An
empty list if not
:Usage:
elements = driver.find_elements_by_id('foo')
"""
return self.find_elements(by=By.ID, value=id_)
def find_elements_by_xpath(self, xpath):
"""
Finds multiple elements by xpath.
:Args:
- xpath - The xpath locator of the elements to be found.
:Returns:
- list of WebElement - a list with elements if any was found. An
empty list if not
:Usage:
elements = driver.find_elements_by_xpath("//div[contains(@class, 'foo')]")
"""
return self.find_elements(by=By.XPATH, value=xpath)
如果使用这种方式来帮助定位元素?
方式一: 通过多个属性叠加进行查找。
例如某个页面中存在多个 span ,其中的 textContent 值不一样。这时可以先通过 tag name = span 找到符合条件的元素数组,然后从数组中逐个对比,查找到符合条件的元素:
def find_span_element_by_text(text):
elements = driver.find_elements_by_tag_name('span')
if len(elements):
for element in elements:
if text in element.get_property('textContent'):
return element
return None
## 如果span 列表中某个元素包含 text ,则返回该元素; 否则,返回 None
方式二:如果页面中有固定数量的相同元素,且位置固定,可以通过数组的下标来定位。
def find_element_by_index(method, value,index):
elements = driver.find_elements(by=method, value=value)
if len(elements)>index:
return elements[int(index)]
else:
return None
## 返回符合条件的元素数组中指定位置的元素