在进行UI自动化的过程中,个人觉得正确定位页面元素是自动化步骤能够正常执行下去的关键。初学过程中,我个人经常因为定位元素不准确而导致测试用例无法成功执行。
selenium为我们提供了多种定位页面元素的方法,我们可以根据用例需求选择不同的方法去使用。
1. 私有方法(private methods):find element() 和find elements()
先给大家介绍两个定位页面元素的私有方法。为啥称这两个方法为私有方法呢?其实我也不太清楚,只是官方文档是这样说的。🙈 这里先给大家介绍这两个定位元素的方法,有一个原因是因为,当我们使用PO模型设计UI自动化框架的时候,相交于公共方法,这两个方法更加灵活,是我们常用的定位元素的基础方法。 而且查看公共方法的源码后,我们可以发现,公共方法归根结底都调用了这两个私有方法,可以说这两个私有方法是“祖宗”。
1.1 find element() :
源码:
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
"""
if self.w3c:
if by == By.ID:
by = By.CSS_SELECTOR
value = '[id="%s"]' % value
elif by == By.TAG_NAME:
by = By.CSS_SELECTOR
elif by == By.CLASS_NAME:
by = By.CSS_SELECTOR
value = ".%s" % value
elif by == By.NAME:
by = By.CSS_SELECTOR
value = '[name="%s"]' % value
return self.execute(Command.FIND_ELEMENT, {
'using': by,
'value': value})['value']
说明:
通过阅读源码及源码中的说明,其实我们就能知道这个方法的使用方法及返回内容。(所以说,大家遇到不会不太理解的方法时,阅读源码会带给你惊喜哦!😎)
element = driver.find_element(By.ID, 'foo')
- 示例:定位百度主页的“百度一下”这个button。
上图,查看页面元素,可以知道“百度一下”这个button的id值为“su”,所以我们可以用id进行定位,
from selenium import webdriver
from selenium.webdriver.common.by import By
class TestDemo():
def setup(self):
self.driver=webdriver.Chrome()
self.driver.maximize_window()
self.driver.implicitly_wait(5)
def teardown(self):
self.driver.quit()
def test_demo(self):
self.driver.get("https://www.baidu.com/")
el=self.driver.find_element(By.ID, 'su')
print(el)
- 注意点:
- find_element()主要是用于定位一个页面元素,返回的是一个WebElement类型的对象。
- find_element()默认使用ID进行元素定位,因此咱们上面的示例也可以这样写
driver.find_element('su') 。 - 使用find_element()定位元素,如果没有定位到元素的话,是会直接报错的。
1.2 find elements()
源码:
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
"""
if self.w3c:
if by == By.ID:
by = By.CSS_SELECTOR
value = '[id="%s"]' % value
elif by == By.TAG_NAME:
by = By.CSS_SELECTOR
elif by == By.CLASS_NAME:
by = By.CSS_SELECTOR
value = ".%s" % value
elif by == By.NAME:
by = By.CSS_SELECTOR
value = '[name="%s"]' % value
return self.execute(Command.FIND_ELEMENTS, {
'using': by,
'value': value})['value'] or []
说明:
element = driver.find_elements(By.ID, 'foo')
- 示例:定位百度主页的右上角的一列元素
上图中,左上角一列的元素的classname都相同,为“mnav”,所以我们可以使用classname来查找这些元素。
from selenium import webdriver
from selenium.webdriver.common.by import By
class TestDemo():
def setup(self):
self.driver=webdriver.Chrome()
self.driver.maximize_window()
self.driver.implicitly_wait(5)
def teardown(self):
self.driver.quit()
def test_demo(self):
self.driver.get("https://www.baidu.com/")
el=self.driver.find_elements(By.CLASS_NAME,'mnav')
print(el)
- 注意点:
-
find_elements()是用来定位一些页面元素,定位成功后,会返回WebElement类型的对象的列表。 -
find_elements()默认使用ID进行元素定位。 -
使用find_elements()定位元素,如果没有定位到元素的话,会返回一个空列表,不会直接报错。不会直接报错终止测试用例运行这一特点,在后面我们开发自己的测试框架时会很有用。
2. 公共方法(public methods)
selenium为我们提供多个公共方法,方便我们进行页面元素的定位。
2.1 定位一个页面元素 的公共方法:
- find_element_by_css_selector
- find_element_by_xpath
- find_element_by_id
- find_element_by_name
- find_element_by_link_text
- find_element_by_partial_link_text
- find_element_by_tag_name
- find_element_by_class_name
2.2 定位多个页面元素 的公共方法:
- find_elements_by_css_selector
- find_elements_by_xpath
- find_elements_by_name
- find_elements_by_link_text
- find_elements_by_partial_link_text
- find_elements_by_tag_name
- find_elements_by_class_name
查看以上方法的源码后,其实可以发现,这些方法都是调用了find_element() 和find_elements() 的。我们选择find_elements_by_css_selector() 这个方法的源码为示例。
find_elements_by_css_selector()的源码:
def find_elements_by_css_selector(self, css_selector):
"""
Finds elements by css selector.
:Args:
- css_selector - CSS selector string, ex: 'a.nav#home'
:Returns:
- list of WebElement - a list with elements if any was found. An
empty list if not
:Usage:
elements = driver.find_elements_by_css_selector('.foo')
"""
return self.find_elements(by=By.CSS_SELECTOR, value=css_selector)
所以这里不会对这些方法进行深入的说明,大家可以通过使用Pycharm查看的源码的方式来了解这些方法如何进行使用。
3. XPath和CSS Selector语法
以上我们介绍的这些selenium提供的元素定位的公共方法,归根结底都是使用CSS Selector和XPath语法来进行定位的。 find_element_by_xpath 和find_elements_by_xpath 是使用XPath语法来进行定位,其余方法都是使用CSS Selector语法来进行定位,所以我们需要熟练的掌握这两种语法。
3.1 XPath
什么是XPath?
XPath全称为XML Path Language,作用于xml语言,可用于解析html和xml。XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。appium和selenium都可使用XPath进行元素定位。
XPath语法 目前网上有很多详细的XPath语法教学说明,讲解非常细致,所以此处给大家贴出我自学时使用的内容,大家可自行前往学习。 XPath语法
XPath的缺点 由于XPath是通过路径从头到尾一点点遍历,所以速度很慢。
3.2 CSS Selector
CSS Selector语法 目前网上有很多详细的CSS Selector语法教学说明,讲解非常细致,所以此处给大家贴出我自学时使用的内容,大家可自行前往学习。 CSS选择器
CSS Selector优点 CSS Selector是使用样式定位,不需要从头到尾一点点进行遍历,因此定位元素的速度比Xpath快。在条件允许的情况,建议优先使用CSS Selector进行定位。
查看公共方法源码后,我们可以发现by_id、by_name、by_link_text、by_partial_link_text、by_tag_name、by_class_name这些公共方法其实是使用CSS Selector进行元素定位的。
|