百度一下 迪丽热巴。这样的一个用户行为 ,会涉及的那些操作呢?
1、打开浏览器2、在输入框里面输入关键词【迪丽热巴】
PS:当然这里可能还涉及到一个操作,回车执行操作。
或者说:点击 “百度一下” 按钮。
只是说现在的浏览器将执行操作设置成自动执行了。3、在搜索完成之后,关闭浏览器
操作的大致流程就是这样的,那么自动化脚本该如何去写呢?
1、打开我们的 IDEA 编译器,新建一个Maven项目
2、创建测试脚本文件
selenium 的 依赖我们去 Maven 的中央厂库里下载。注意!千万不要下载 3.0版本 的 selenium,它的语法有所不同。
链接https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java
org.seleniumhq.selenium selenium-java 4.0.0 接下来,哦们就来使用 selenium
此时,脚本代码的测试逻辑已将完成了。
下面,我们回到 RunTest 类,去使用它。下面我们执行这个类,你们就能看到现象:自动打开浏览器,进入到百度网页,输入关键词进行查询。查询之后,自动关闭浏览器。
1、CSS 选择器【cssSelector 方法】
如果你不懂前端的知识,有更简单获取 css 选择器 的方式:
复制到的就是: .s_ipt
WebElement element = webDriver.findElement(By.cssSelector(".s_ipt"));
2、xpath 选择器 - 了解
xpath 语法:
1、层级: / 【表示 次级】; // 【表示 跳级】
2、属性: @ 等等。。。
3、函数: contains()等等。。。复制到的就是://*[@id=\"kw\"]
WebElement element = webDriver.findElement(By.xpath("//*[@id=\"kw\"]"));
效果我就不展示了,都一样。
需要注意的是:定位的元素必须要唯一。
意思就是说:
无论我们复制的是 css,还是xpath,都有可能找到复数的结果。
那么,就很有可能导致查询的结果,与预期结果不一样!
我们可以通过下面的方法来检查元素的唯一性。
前面讲到了不少知识都是定位元素,定位只是第一步,定位之后需要对这个元素进行操作。
是鼠标点击,还是键盘输入,或者清除元素的内容,或者提交表单等。
这个取决于定位元素需要进行的下一步操作。
其实在我们演示的自动化脚本中,我们已经对元素进行操作了。后面的输入关键词,以及点击 百度一下的按钮,都是对元素的操作。
元素的操作,又称操作测试对象。
webdriver 中比较常用的操作对象的方法有下面几个:
1、click 点击对象
2、sendKeys 在对象上模拟按键输入
3、clear 清除对象输入的文本内容
4、submit 提交【等价于 click】click 和 submit 都可以操作按钮
【前提:submit 操作的是按钮】
可以使用 submit 的地方,都可以使用 click 来实现。
文本样式的超链接的触发,只能通过 click(点击)的方式来触发。
如果使用 sumbit 的方式来触发,就会报错。
在 selenium 官方文档中,更推荐使用 click
不推荐使用 submit。另外,为什么我们是使用的 String 类型 来接收 getText 的 返回值呢?
我们来分析一下原因:
那么,我们如何获取到 标签的属性值呢?
使用 getAttribute 方法通过指定属性名称,来获取指定的属性值。
下面我们把这个看似 “没问题” 的操作流程,来执行一下。
这里的延时(等待)操作,是非常重要的,关乎到脚本是否能正常运行!
我们这里所采用的方式是属于:强制等待
让程序强制等待3s之后,给予前端页面加载的时间,再执行下一条程序。
优点:
语法简单,适合测试的时候复用。
缺点:
效率很低!【延长测试时间】我们使用自动化测试 的 目的 就在于 提升效率。
将 人工测试操作 交由机器来进行,节省人力成本。
并且机器的执行效率是非常高的,这样就节省了时间成本(效率得到了提升)。
但是由于我们的强制等待操作,让程序执行的过程中出现了 “停顿”,这毫无疑问会影响程序的执行效率。这种问题在 C++ 中是不被允许存在的!
另外,如果每个测试用例使用 强制等待的时间平均为 3 ~ 5s
我们以 5s 为例,通常一个web自动化测试用例与几百个,我们假如测试用例有 100个。
那么,强制等待的时间:100 x 5 == 500 s 约等于 8分钟.20s
还没完!还要加上 自动化测试脚本执行的时间呢!
考虑最坏情况(硬件环境,软件环境,网络环境都不太理想的情况),自动化测试的时间可能会超过 15 min,甚至更久!
一刻钟,这是非常久的!
像我们这个测试用例执行的时间,如果不加sleep,(软硬件都非常给力的情况)执行 0.01s 都算是非常漫长的时间!!!
更别说 15 分钟了,简直就是离谱!!!那么,存不存在一种更高效的方法?
在获取(定位)一个元素的时候,如何没有获取到,进行等待,一旦元素加载完成,立即获取。
也就是说:等待的时间不再是固定的,而是自适应。
下面,我们就看看 “隐式等待”。
简单来说:
在规定的时间范围内,轮询等待元素出现之后就立即结束。
如果在规定的时间范围内,元素仍然没有出现,则会抛出一个异常【NoSuchElementException】,脚本停止运行。没有报错,执行过程非常丝滑!
另外, 隐式等待 作用于 WebDriver 整个生命周期。
【只要没有走到 driver.quit,即没有退出浏览器,隐式等待都是一直存在的】
所以,隐式等待的代码的位置,可以随意。
需要注意的是:
规定的时间要合理,时间太短,那就和没设置一样了。
优点:
节省了大量的等待时间,元素展示之后,就可以直接执行下一步。
缺点:
需要等待页面元素全部加载完成,才能执行下一步。
因此,仍然会有额外的时间浪费。【但是比强制等待要强一点】
这里我们需要使用到 selenium 里中的一个类 ExpectedConditions,以及 until 方法。
如果在规定的等待时间内,没有找到元素,就会报异常【NoSuchElementException】。
至于代码运行,非常丝滑,没有问题。
非要说有问题的话:写法太复杂了。
ExpectedConditions 类中还有很多其它的方法
优点:
针对某一个元素来进行等待,极大降低了自动化整体的等待时间。
缺点:
写法相比前面两种,要复杂一些。
代码里面是可以同时使用显示等待和隐式等待!
但是!不推荐!
因为同时使用可能会造成一些意向不到的结果。
比如:
显示等待10s,隐式等待 5s。【等待时间不可以累加】
那么它等待时间可能是 10s,11s。。。。
总之等待时间不是固定的,
我们先来做一些准备工作。
创建新的包 和 测试脚本类
下面我们就来书写 messagePrint 方法。
方法很简单,直接中译英:获取当前网址 -> getCurrentUrl
这里我们来增加一丢丢难度,我们来获取 点击 新闻之后的网址。
下面我们来修改一下代码
我们怎么去获取到句柄呢?
这就关乎到下一个内容:窗口
通过 driver 的 getWindowHandle 方法 来获取句柄.
我们来调用一下这个方法。
我们再来试试 上一个案例的情况,看看是否能获取到 新页面的句柄
此时,我们得出结论:
getWindowHandle 方法无法感知新键页面
getWindowHandles 可以获取到所有页面的句柄(唯一标识).
那么问题来了,我们如何切换到最新页面呢?
关键就在于 getWindowHandles 上。
想要跳转到想要去的页面,从 getWindowHandles 的结果集(allWindow)中获取。重点就在于 getWindowHandle 和 getWindowHandles 方法的配合。
再通过 switchTo.window 方法 来进行页面跳转。
其实每次都要从一个页面跳转到另一个页面,不如直接 driver.get( url ) 直接访问来的简单。
像这种辗转操作,其实在自动化测试中,并不常见。
这个很简单,自己尝试一下
相信大家都遇到过浏览器 “一键置顶”的功能。
点击一个 按钮,窗口自动回到 页面顶部那么,有一键置顶,就有一键置底
关于这个方法 selenium 提供了 driver.executeScript 方法。
意思就是执行一个 JS 语言(脚本),完成某项操作。
【PS:selenium 是无法直接编译 js 语言的,所以只能通过上面这个方法来执行】
我们先来看置底操作【window.scroll(0,document.body.scrollHeight)】再来看置顶操作【window.scroll(0,document.body.scrollTop)】
在 selenium 中 使用,就是将我们刚才那两条脚本语言 复制到 driver.executeScript 方法中。
调用的时候,先调用 windowTest 方法 来切换页面,再来调用 windowTest2 来操作界面。
效果没有问题,我执行了。
我以CSDN为例
接下来,我们就是要实现一组这样的操作。【页面的前进与后退】
selenium 里提供了 navigate 接口 来实现页面的导航
- 浏览器的前进通过 driver.navigate().forward()
- 浏览器的后退通过driver.navigate().back()
但是问题来了,我们的例子是在一个页面中执行。
如果是那种点击之后创建新页面的情况呢?答案是:不会跳转回到之前的页面。
因为弹出的是一个新的页面,与原先的页面并不是前后的关系。
有点类似于 转发 和 重定向 之间的关系。
我们这个在线工具网站就相当于 转发。【同源】
新建页面 就相当于重定向。【异源】
我就网上随便找了几个图,我就说一下思路。
就是找到点击键,点击之后,弹出窗口后,在锁定 关闭窗口键元素,进行点击(click)
【 driver.findElement(By.cssSelector(“”)).click();】但是!,还有一种情况:弹窗元素无法选中的情况。
这种类型的弹窗被我们称为 “警告弹窗”
这种弹窗是无法通过 driver.findElement()方法 来定位元素。
这里需要用到 selenium 中提供的 Alert 接口。另外,有确认按钮,那么就有 取消按钮
还有一种特别的弹窗,可以让我们进行输入
这里的输入框也是无法定位的!
想要输入内容也很简单!还是使用 sendKeys 方法
selenium 提供了 Actions 接口,来模拟 鼠标的操作。
代码如下
虽然上述操作中,通过对元素的定位完成了选择。
但是,我们是要模拟 鼠标 操作的,因此我们需要鼠标 “动起来”,通过鼠标去点击选择。
键盘的操作,我们已经用过了,就是 sendKeys 方法
下面的这个场景才是真正的 下拉菜单,上面那个算是点击菜单
selenium 就是提供了 select 接口
还有最后一个方法:根据可见文本来选择
此时,我们来思考一件事:能不能定位 系统框中的元素,并进行操作?
selenium 不能直接操作系统框。
但是,这个操作是可以模拟实现。【sendKeys方法 输入 上传文件路径(包含文件名称)】
这里我们回顾一下前面的内容:
我们在百度页面搜索关键词 “迪丽热巴”,然后从中获取到某些数据。
在不添加等待的情况下,由于代码执行的速度过快,导致页面元素获取不到【页面元素还未加载完成】,从而抛出异常 【NoSuchElementException】如果我不告诉你:获取不到元素的原因,你能推导出原因吗?
这个时候就可以使用屏幕截图来解决。我对我的代码执行的过程进行 “拍照(截图)”,去发现它的一个问题是什么?
举个例子:
高速公路的车辆行驶速度是非常快的。【类比 代码的执行速度】
而且 在高速公路上是最容易发生 超速问题(元素获取不到的问题)的!
于是就有了高速抓怕摄像头(屏幕截图)来抓住 问题的情况(证据)。selenium 提供了相应的(屏幕截图)方法:driver.getScreenshotAs(OutputType.返回的文件类型);
在使用之间,我们需要导入一个依赖
commons-io commons-io 2.6
代码如下:
注意!我们是没有使用等待的,所以当前这个方法是一定会报异常的,会得到一下截图