selenium学习笔记
selenium学习笔记
格式待完善,增加代码细节以及项目细节,分p
环境配置
pip3 install selenium
下载浏览器对应driver版本,将下载解压的chromedriver放入~/.bash_profile文件配置的路径中
selenium
IDE
chrome插件下载
通过插件录制用例
可以导出代码
等待
直接等待
sleep()
强制等待,线程休眠一定时间
隐形等待
self.driver.implicitly_wait(X)
设置一个等待时间,轮询查找(默认0.5s)元素是否出现,若没有出现则抛出异常
显性等待
在代码中定义等待条件,当条件发生时才继续执行代码
WebDriverWait 配合until()和 until_not(),根据判断条件进行等待
程序每隔一段时间(默认0.5s)进行条件判断,若条件成立,则执行下一步,否则继续等待,知道超过设置的最长时间
web控件定位
点击和输入
XPATH
XML path Language
用于解析html和xml
表达式
nodename 选取此节点的所有子节点
/ 从根节点选取
// 从匹配选择的当前节点选择文档中的节点,而不考虑他们的位置
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性
表达式例子
/bookstore/book[1]
选取属于bookstore子元素的第一个book元素
/bookstore/book[last ()]
选取输入bookstore子元素的最后一个book元素
/bookstore/book[last ()-1]
选取输入bookstore子元素的倒数第二个book元素
/bookstore/book[postion()<3]
选取最前面的两个属于bookstore元素的子元素book元素
//title[@lang-'eng']
选取所有的title元素,且这些元素拥有值为eng的lang属性
/bookstore/book[price>35.00]
选取bookstore元素的所有book元素,且其中的price元素的值需大于35.00
/bookstore/book[price>35.00]/title
选取bookstore元素中的book元素的所有title元素,且其中price元素的值需大于35.00
css selector
https://ceshiren.com/t/topic/11479
选择器
.class - .intro - 选择class=“intro”的所有元素
#id - #firstname - 选择id= “firstname”的所有元素
* 选择所有元素
element - p - 选择所有<p>元素
element,element - div,p - 选择所有<div>和所有<p>元素
element element - div p - 选择所有<div>元素内部的所有<p>元素
element>element - div>p - 选择父元素为<div>元素的所有<p>元素
[attribute] - [target] - 选择带有target属性所有元素
[attribute=value] - [target=_blank] - 选择target="_blank"的所有元素
:nth-child(n) - p:nth-child(2) - 选择属于其父元素的第二个子元素的每个<p>元素
:nth-last-child(2) - 选择属于其父元素的倒数第二个子元素的每个<p>元素
element1~element2 - p~ul - 选择前面有<p>元素的每个<ul>元素
appium 原生控件不支持css selector
ActionChains
执行PC端的鼠标点击,双击,右键,拖拽等事件
执行原理
调用ActionChains的方法时,不会立刻执行,而是将所有的操作,按顺序排放在一个队列里,调用perform() 时,队列重的时间会依次执行
具体写法
链式写法
ActionChains(driver).move_to_element(element).click(element).perform()
分布写法
action = ActionChains(driver)
action.move_to_element(element)
actions.click(element)
actions.perform()
常见操作
click(on_element=None) —— 点击鼠标左键
click_and_hold(on_element)=None —— 点击鼠标左键,不松开
context_click(on_element)=None —— 点击鼠标右键
double_click(on_element)=None —— 双击鼠标左键
drag_and_drop(source, target) —— 拖拽到某个元素到目标位置后松开
drag_and_drop_by_offset(source, xoffset,yoffset) —— 拖拽到某个坐标然后松开
move_by_offset(xoffset,yoffset) —— 鼠标从当前位置移动到某个坐标
move_to_element(to_element) —— 鼠标移动到某个元素
move_to_element_with_offset(to_element,xoffset,yoffset) —— 移动到距某个元素(左上角坐标)多少距离的位置
preform() —— 执行链中所有动作
release(on_element=None) —— 在某个元素位置松开鼠标左键
send_keys(*keys_to_send) —— 发送某个键到当前焦点的元素
key_down(value,element=None) —— 按下某个键盘上的键
key_up(value,element=None) —— 松开某个键
find_element_by_link_text 方式定位,标签必须是<a></a>的元素
TouchActions
模拟PC和移动端的点击,滑动,拖拽,多点触控等多种手势操作
手势控制
tap —— 在指定元素上敲击
double_tap —— 在指定元素上双击
tap_and_hold —— 在指定元素上点击但不释放
move —— 手势移动指定偏移(未释放)
release —— 释放手势
scroll —— 手势点击并滚动
scroll_form_element —— 从某个元素位置开始手势点击并滚动(向下滑动为负数,向上滑动为正数)
long_press —— 长按元素
flick—— 手势滑动
flick_element —— 从某个元素位置开始手势滑动(向上滑动为负数,向下滑动为正数)
Perform 执行
表单结构
多窗口处理与网页frame
获取窗口的唯一标识用句柄表示,所以只需要切换句柄,就可以在多页面灵活操作
处理流程
1, 先获取当前的窗口句柄 driver.current_window_handle
2, 再获取到所有的窗口句柄 driver.window_handles
3, 判断是否想要操作的窗口,不是当前想操作的窗口就需要跳转到另一窗口 driver.switch_to_window
frame
元素定位不到时有可能是在iframe中
frame是html的框架,在同一浏览器中显示不止一个页面
基于html的框架,又分为垂直框架cols和水平框架rows
分类
frame标签包含frameset,frame,iframe
frameset和普通标签一样,不会影响正常的定位,可以使用index,id,name,webelement任意方式定位frame
多frame
嵌套
对于嵌套的先进入到iframe的父节点,再进到子节点,然后可以对子节点里面的对象进行处理和操作
driver.switch_to.frame("父节点")
driver.switch_to.frame(“子节点”)
未嵌套
driver.switch_to_frame("frame的id")
直接使用id切换
driver.switch_to_frame("frame-index")
frame无ID的时候依据索引来处理,索引从0开始driver.switch_to_frame(0)
切换frame
driver.switch_to.frame() # 根据元素id或者index切换frame
driver.switch_to.default_content() #切换到默认frame
driver.switch_to.parent_frame() #切换到父级frame
文件上传
input标签可以直接使用send_keys(文件地址)上传文件
用法:driver.find_element_by_id('上传按钮id').send_keys("文件路径+文件名")
send_keys上传的文件一定是绝对路径吗?
chrome 开启debug模式?2020
启动chrome时需要先推出所有chrome进程。使用ps aux|grep chrome|grep -v 'grep'查看是否有chrome进程存在
弹框处理机制
alert,confirm及prompt弹框
定位方法:switch_to.alert()
操作alert常用的方法
switch _to.alert() 获取当前页面上的警告框
text 返回alert/confirm/prompt中的文字信息
accept() 接受现有警告框
dismiss() 解散现有警告框
send_keys(keysToSend) 发送文本至警告框
多浏览器处理
支持多浏览器
传不同参数测试不同的浏览器,浏览器的兼容性测试
JavaScript脚本
脚本例子
document.title
window.alert("xx")
JSON.stringify(performance.timing)
获取当前页面的性能数据
document.documentElement.scrollTop=50
滑动页面到指定位置
selenium调用JS
execute_script 执行js
return 可以返回js的返回结果
execute_script:arguments 传参
时间控件
大部分时间控件都是read only属性,需要手动去选择对应的时间,手工测试中很容易做到,自动化中对控件的操作可以使用js来操作
处理时间控件的思路:
1,取消日期的read only 属性
2,给value赋值
1-2点使用js代码实现,再使用webdriver对js进行处理
复用浏览器
chrome 开启debug模式
mac 启动命令:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome - -remote-debugging-port=9222
相关信息会打印在命令行中
需要在命令行中先启动,再用代码运行
cookie保存
yaml
yaml.load 读取文件
yaml.dump 写入文件
PO设计模式
原则
方法意义
用公共方法代表UI所提供的功能
方法应该返回其他的PageObject或者返回用于断言的数据
同样的行为不同的结果可以建模为不同的方法
不要在方法内加断言
字段意义
不要暴露页面内部的元素给外部
不需要建模UI内的所有元素
相关官网
https://www.selenium.dev/documentation/en/guidelines_and_recommendations/page_object_models/
https://martinfowler.com/bliki/PageObject.html
实战练习的思路
梳理测试用例
构造PO模型
构造页面相关类和方法
编写测试用例
根据业务逻辑编写
链式调用
填充具体实现
Driver初始化
初始化放在BasePage类中,其他Page类继承BasePage即可,子类可以使用父类的属性,直接通过self.driver调用driver实例对象
BasePage封装
优化用例
封装样板代码
直接调用selenium API,导致存在大量的样板代码,类似与find_element、find_elements 等,将常用的UI操作封装在base_page中
提取页面元素
页面定位(By.id, "xxx")在每个Page的方法中,如果此页面定位存在多处复用,需要多处修改 -- 将该页面定位抽离出来声明为私有类变量,避免暴露页面内部的元素,符合PO六大原则
添加起始页的url
起始url 不应该写在basepage中,basepage和具体业务没有任何关联,每个UI用例的开始都可以不从首页开始--每个Page子类添加_base_url变量。确保即使用例从子类页面起始

浙公网安备 33010602011771号