
(二)UI 自动化测试selenium
UI 自动化测试selenium(二)
css选择器
CSS选择器的调试方式(也就是开发者模式的Console):
$("[id='title']")
有的需要输入两个$$
$$("[id='title']")
##基础使用
#****************************************************************
# 选择所有div标签
driver.find_elements(By.CSS_SELECTOR, "div")
# 选择ID为modal的元素
driver.find_element(By.CSS_SELECTOR, "#modal")
# 选择class类为new的元素
driver.find_element(By.CSS_SELECTOR, ".new")
# 选择href类内容为/的元素
driver.find_element(By.CSS_SELECTOR, '[href="/"]')
er中用法示例的表格:
类型 | 表达式 | 示例 |
---|---|---|
标签 | 标签名 |
|
类 | .class属性值 |
|
ID | #id属性值 |
|
属性 | [属性名=‘属性值’] |
|
进阶使用
类型 | 格式 | 示例 |
---|---|---|
父子关系+顺序 | 元素:nth-child(n) |
|
父子关系+标签类型+顺序 | 元素:nth-of-type(n) |
|
类型 | 格式 | 在console中的写法示例 |
---|---|---|
并集 | 元素,元素 |
|
邻近兄弟(了解即可) | 元素+元素 |
|
兄弟(了解即可) | 元素1~元素2 |
|
父子 | 元素>元素 |
|
后代 | 元素 元素 |
|
##进阶使用
#****************************************************************
driver.find_element(By.CSS_SELECTOR, 'div.footer1 > span.copyright')
# 或者使用类选择器方式
driver.find_element(By.CSS_SELECTOR, '.footer1 > .copyright')
# 多元素选择,选取类名为footer1的元素和类名为copyright的元素
driver.find_elements(By.CSS_SELECTOR, '.footer1, .copyright')
# 选取第2个子元素且为<code>标签的元素
driver.find_element(By.CSS_SELECTOR, 'code:nth-child(2)')
# 选取第2个<code>标签类型的元素
driver.find_element(By.CSS_SELECTOR, 'code:nth-of-type(2)')
# 选取<code>标签之后紧跟的第一个<div>标签
driver.find_element(By.CSS_SELECTOR, 'code + div')
# 选取<code>标签之后所有的<div>标签
driver.find_elements(By.CSS_SELECTOR, 'code ~ div')
##进阶使用
#****************************************************************
# 选择class类为new、button的元素(html中是class=new button)需要把空格换成.
driver.find_element(By.CSS_SELECTOR, ".new.button")
# 类名为navbar-brand并且href为/的a标签
driver.find_element(By.CSS_SELECTOR, 'a.navbar-brand[href="/"]')
# 选择<a>标签且href属性为"/"的元素
driver.find_element(By.CSS_SELECTOR, 'a[href="/"]')
# 选择ID为modal的元素内部的所有div元素
driver.find_elements(By.CSS_SELECTOR, '#modal div')
# 类名中包含modal的元素(所有含 modal 的 class)
driver.find_elements(By.CSS_SELECTOR, '[class*="modal"]')
# 所有class属性以mo开头的a元素
driver.find_elements(By.CSS_SELECTOR, 'a[class^="mo"]')
# 所有class属性以al结尾的a元素
driver.find_elements(By.CSS_SELECTOR, 'a[class$="al"]')
# 同时具有多个属性的div元素
driver.find_element(By.CSS_SELECTOR, 'div[class="modal"][role="dialog"]')
# 类名为footer1的div元素下的直接子元素,其类名为copyright的span元素
Xpath选择器
Xpash本来是在XML文档中进行检索的语言
使用的是路径表达式
支持显示文本定位(html中黑色文字)
Xpath的调试方式:$x("表达式")
表达式 | 结果 | 示例 |
---|---|---|
/ | 从该节点的子元素选取 |
|
// | 从该节点的子孙元素选取 |
|
* | 通配符 |
|
nodename | 选取此节点的所有子节点 |
|
.. | 选取当前节点的父节点 |
|
@ | 选取属性 |
|
实现了从子查父,也能从父查子,非常方便,基本上能解决99%的定位难题
# 获取[@id='ember21']节点下的所有的li元素
$x("//*[@id='ember21']//li")
# 获取[@id='ember21']节点下所有的节点的第一个li元素
$x("//*[@id='ember21']//li[1]")
XPath 表达式 | 描述 | 示例 |
---|---|---|
//div[text()=‘3’] | 搜索显示特定文字的div元素 |
|
/html/div/span/h1 | 按给定顺序寻找路径 |
|
//div//span | 所有的div下面的所有span |
|
//*[@class=‘cawada’] | 搜索具有特定class属性的元素 |
|
//*[contains(@style,‘color’)] | 模糊搜索style属性包含color的元素 |
|
//*[starts-with(@style,‘color’)] | 搜索style属性以color开始的元素 |
|
//p[2] | 搜索第二个p元素 |
|
//div/p[2] | 搜索div元素的第二个直接子元素p |
|
//p[last()-1] | 搜索倒数第二个p元素 |
|
//p[position()<=2] | 搜索位置在前两位的p元素 |
|
//[@class=‘xx’]/following-sibling:: | 搜索具有特定class的元素的所有兄弟节点 |
|
following-sibling::* | 选择前面的兄弟节点 |
|
/input[@name='passward' and @pwd='123456'] | 使用and分割,多属性查找(or满足一个即选择) |
|
//*[@id=‘china’]/… | 选择具有特定id的元素的父节点 |
|
显式等待原理
WebDriverWait类
先看看传入什么参数:
参数:
1.实例化的浏览器驱动
2.最长等待时间
3.轮询等待时间,默认为0.5s
until方法
注意!这个method传的是函数对象!
def func(driver):#这里为什么要传参?看看下一图片的value=method(self._driver)
print("123")
WebDriverWait(driver,10,1).until(func) # 这里不要使用func()!
# 这里因为没有设置func的返回值,所以会一直轮询,直到最大等待时间
实现方法:
我们来看看之前写的简单的显式等待:
from selenium.webdriver.support import expected_conditions #导入expected_conditions
def wait_until():
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
WebDriverWait(driver, 10).until( expected_conditions.element_to_be_clickable( (By.CSS_SELECTOR, '#success_btn')))
driver.find_element(By.CSS_SELECTOR, "#success_btn").click()
expected_conditions.element_to_be_clickable()
这个方法是什么?
从导入信息可以看出来是来自elenium.webdriver.support的方法,实现的功能是元素如果可以点击则返回True
这里返回的target其实是WebElement类型:
所以可以省略为:
from selenium.webdriver.support import expected_conditions #导入expected_conditions
def wait_until():
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
WebDriverWait(driver, 10).until( expected_conditions.element_to_be_clickable( (By.CSS_SELECTOR, '#success_btn'))).click()
support库里的确有很多的方法,但是也还有有局限性,我们得学会如何自定义显式等待:
显示等待其实可以理解为
一个循环
,直到你的函数返回True或者不为None的值
现在有一个场景,你需要设计一个显式等待来实现不断点击,直到你弹窗出现才停止
# 需求:连续点击,直到弹窗出现
# 先明确参数, 1、点击的参数 2、弹窗的参数
# 再明确返回值:如果出现弹窗返回True或者元素,没有弹窗返回None
def func(click_arg, pop_arg):
def _predicate(driver):#头和尾巴是直接从support库中copy过来
driver.find_element(*click_arg).click()#点击
return driver.find_element(*pop_arg)#返回
return _predicate
def test_wait_until():
driver = webdriver.Chrome()
driver.get("https://URLTEST")
WebDriverWait(driver, 10).until(func((By.CSS_SELECTOR, '#primary_btn'),(By.XPATH, '//span[text()="该弹框点击两次后才会弹出"]')))
time.sleep(5)
其实WebDriverWait源码中还有个not_until,这里不展开细讲,可以自行研究。