参考文档
注:本文借助pytest实现自动化case
目录
- 简介
- 安装selenium库
- webDriver安装配置
- 第一个selenium程序
- 编写第一条测试用例
- selenium三种等待方式
- web控件定位与常见操作
- xpath定位
- css定位
- web控件的交互
- 表单操作
- 多窗口处理与网页frame
简介
用于web浏览器测试工具,支持的浏览器包括IE、Firefox、Safari、Chrome等。
使用简单,可以使用Java、Python等多种语言编写。
主要由三个工具构成:webdriver/ide/Grid。
安装
安装selenium库
1 | pip --default-timeout=100 install selenium==3.141.0 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com |
webDriver安装配置
Driver介绍:
1 | https://www.selenium.dev/zh-cn/documentation/webdriver/ |
Driver下载:
1 | 官方地址: |
第一个selenium程序
新建test_selenium.py文件,复制如下代码:
1 | from selenium import webdriver |
执行:
1 | pytest -vs .\test_demo.py |
说明:可以正常打开Chrome浏览器并访问百度及证明环境搭建完成。
编写第一条测试用例
测试用例的核心要素:
- 一条测试用例的最终结果只有一个,成功or失败。
- 三大核心要素为:标题、步骤、断言
- 标题:是对测试用例的描述。
- 步骤:对测试执行过程进行描述。
- 断言:实际结果与预期结果对比。
新建test_search.py文件,复制如下代码:
1 | from selenium import webdriver |
执行:
1 | pytest -vs test_search.py |
输出:
1 | collected 1 item |
说明:能够成功打开浏览器并搜索selenium。
selenium三种等待方式
- 直接等待:
强制等待,休眠一定时间。
1 | time.sleep() |
- 隐式等待:
设置一个等待时间,轮训查找(默认间隔0.5s)元素是否出现,如果时间内没有出现则抛出异常。
为全局设置
1 | driver.implicitly_wait(5) |
- 显示等待:
在代码中定义等待条件,当条件发生时才继续执行代码。
‘WebDriverWait’配合until()或until_not()方法,根据判断条件进行等待。
程序每隔一段时间(默认0.5s)进行条件判断,如果条件成立,则执行下一步,否则继续等待,直到超过设置的最长时间。
web控件定位与常见操作
selenium的点击与输入
1 | driver.find_element(By.ID,"kw").send_keys("selenium") |
xpath定位
表达式 | 描述 |
---|---|
/booksotre/book[1] | 选取booksotre子元素的第一个book元素 |
/booksotre/book[last()] | 选取booksotre子元素的倒数第一个book元素 |
/booksotre/book[lst()-1] | 选取booksotre子元素的倒数第二个book元素 |
/booksotre/book[position()<1] | 选取最前面的两个属于booksotre子元素的book元素 |
//title[@lang=”eng”] | 选取所有title元素,且这些元素拥有值为eng的lang属性 |
/booksotre/book[price()>35] | 选取booksotre元素所有book元素,且其中的price元素值必须大于35 |
/booksotre/book[price()>35]/title | 选取booksotre元素所有title元素,且其中的price元素值必须大于35 |
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点 |
/ | 从根节点选取 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
css定位
表达式 | 示例 | 描述 |
---|---|---|
.class | .intro | 选择class=”intro”的所有元素 |
#id | #firstname | 选择id=”firstname”的所有元素 |
* | * | 选择所有元素 |
element | p | 选择所有 标签元素 |
element,element | div,p | 选择所有 标签元素和所有 标签元素 |
element element | div p | 选择所有 标签元素内的 标签元素 |
element>element | div>p | 选择父元素为 标签元素的 标签元素 |
element+element | div+p | 选择紧接在 标签元素之后的 标签元素 |
注意:
css selector定位是非常核心的定位方式,其它定位比如 id定位,name定位等,最终都是通过 css selector来完成的。
下面贴一段webdriver中 find_element方法的源码:
1 | def find_element(self, by=By.ID, value=None): |
web控件的交互
常用的操作事件(右键点击,页面滑动,表单操作等等)
Actions:
- ActionChains:执行PC端的鼠标点击,双击,右键,拖拽等事件。
- TouchActions:模拟PC和移动端的点击,滑动,拖拽,多点触控等多种手势操作。
ActionChains:
执行原理:
调用ActionChains方法时,不会立即执行,而是将所有的操作按顺序存放在一个队列中,当调用perform()方法时,队列中的事件会依次执行。
基本用法:
生成一个动作action=ActionChains(driver)
添加方法1: action.方法1
添加方法2: action.方法2
…
…
调用perform()方法执行(action.perform())
具体写法:
链式写法:
1 | ActionChains(driver).move_to_element(element).click(element).perform() |
分布写法:
1 | action=ActopnChains(driver) |
示例1:点击,双击,右键
1 | action=ActionChains(driver) |
新建test_ActionChains.py文件,复制如下代码:
1 | import pytest |
执行case:
1 | pytest -vs test_ActionChains.py::TestActionChains::test_case_click |
示例2:鼠标移动到某个元素上
1 | action=ActionChains(driver) |
打开上面的test_ActionChains.py文件,添加如下代码:
1 | def test_case_move_to(self): |
执行case:
1 | pytest -vs test_ActionChains.py::TestActionChains::test_case_move_to |
示例3:将一个元素拖拽到另一个元素
有三种方法实现:
1 | action=ActionChains(driver) |
打开上面的test_ActionChains.py文件,添加如下代码:
1 | def test_case_drag_drop(self): |
执行case:
1 | pytest -vs test_ActionChains.py::TestActionChains::test_case_drag_drop |
示例4:ActionChains模拟按键方法
模拟按键有多种方法,能够用win32API来实现,能用SendKeys()来实现,也可以用selenium的WebElement对象的
send_keys()方法来实现,ActionChains类也提供了几个模拟按键的方法。
1 | action=ActionChains(driver) |
打开上面的test_ActionChains.py文件,添加如下代码:
1 | def test_case_keys(self): |
执行case:
1 | pytest -vs test_ActionChains.py::TestActionChains::test_case_keys |
TouchActions:
类似于ActionChains,ActionChains只针对于PC端程序鼠标模拟的一系列操作,对H5页面操作时无效,TouchAction可以对h5进行操作,通过
TouchAction可以实现点击、滑动、拖拽、多点触控、以及模拟手势的各种操作。
手势控制:
- tap–在指定元素上敲击。
- double_tap–在指定元素上双敲击。
- tap_and_hold–在指定元素上点击但不释放。
- move–手势移动指定偏移(未释放)。
- release–释放手势。
- scroll–手势点击并滚动。
- scroll_form_element–从某个元素位置开始手势点击并滚动(向下滚动为负数,向上滑动为正数)。
- long_press–长按元素。
- flick–手势滑动。
- flick_element–从某个元素位置开始手势滑动(向上滑动为负数,向下滑动为正数)。
- preform–执行。
新建 test_touchAction.py文件,复制如下代码
1 | import pytest |
执行case:
1 | pytest -vs test_touchAction.py::TestTouchAciton::test_case_click |
表单操作
表单是一个包含表单元素的区域。
表单元素是允许用户在表单中输入信息的元素。
表单使用表单标签<form>
定义。
操作表单步骤:
首先要定位到表单元素。
然后去操作元素(清空,输入或者点击等)。
例如登录功能等,同其它元素定位操作相同,这里不再过多介绍。
多窗口处理与网页frame
selenium处理多窗口场景
- 多窗口识别
- 多窗口之间切换
多窗口处理:
点击某链接,会重新打开一个窗口,对于这种情况,想在新页面上操作,就得先切换窗口了。
获取窗口的唯一标识用句柄标识,所以只需要切换句柄,就可以在多个页面灵活操作了。
处理流程:
- 先获取到当前窗口的句柄
driver.current_window_handle
- 在获取到所有的窗口的句柄
driver.window_handles
- 判断释放是想要操作的窗口,如果是就直接进行操作,如果不是,就切换到想要操作的窗口
driver.switch_to.window
新建test_windows.py文件,复制如下代码:
1 | import pytest |
执行case:
1 | pytest -vs test_windows.py::TestWindows::test_case_login_window_check |
selenium处理frame
- 多个frame识别
- 多个frame切换
frame介绍:
在web自动化中,如果一个元素定位不到,那么很大可能是在iframe中。
frame是html中的框架,在html中,所谓的框架就是可以在同一个浏览器中显示不止一个页面。
基于html框架,又分为垂直框架和水平框架(cols,rows)。
Frame分类:
Frame标签包含frameset,frame,iframe三种。
frameset和普通标签一样,不会影响正常的定位,可以使用index/id/name/webelement任意种方式定位frame。
而frame与iffame妒忌selenium而言定位是一样的,selenium有一组方法对frame进行操作。
frame切换:
frame存在两种情况:
一种是嵌套的,一种是未嵌套的。
切换frame:
1 | driver.switch_to.frame() # 根据元素id或者index切换frame |
处理未嵌套的iframe:
1 | driver.switch_to_frame("frame 的 id") |
处理嵌套的iframe:
对于嵌套的先进入到父级节点,再进到子节点,然后在对子节点里的对象进行处理操作。
1 |
|
新建test_frame.py文件,复制如下代码:
1 | import pytest |
执行case:
1 | pytest -vs test_frame.py::TestFrame::test_case_frame |
执行JavaScript脚本
selenium执行js:
execute_script:执行js
return:返回js执行结果
新建test_js.py,复制如下代码:
1 | import pytest |
执行case:
1 | pytest -vs test_js.py::TestJs::test_case_js_scroll |
弹窗处理
在操作页面过程中有时会遇见JavaScript所生成的alert/confirm/prompt等弹框,可以使用switch_to.alert()方法定位,
然后使用text/accept/dismiss/send_keys等方法进行操作
alert常用方法:
1 | switch_to.alert():获取当前页面上的警告弹窗 |