一、定位元素的方法 **findElement **和 findElements
首先页面上六个热搜文本对应在 6 个 li 标签中
每个li 标签下的 a 标签 下的 第二个 span 标签存着我们要获取的文本
从代码中可以看到,传入单个标签的情况下只会返回一条文本
传入多个标签则会返回 一个 List<WebElement>
二、对元素进行操作的方法
"百度中输入框为 #kw 百度一下按钮为 #su"
1.sendKeys() 和 click()
效果:sendKeys() 对某个元素进行文本输入
** click() 对某个元素进行点击**
执行效果为: 打开浏览器 -> 在输入框输入 "selenium" -> 停止3s -> 点击百度一下 -> 停止3s -> 关闭浏览器
连续使用 sendKeys() :
如果对同一个输入框元素 连续执行两次 sendKeys 操作,则会实现 "字符串" 拼接的效果
例如 sendKeys("我爱玩");
sendKeys("金铲铲");
那么输入框中就会是 "我爱玩金铲铲";
- clear()
效果:清除元素的文本
- getText() 和 getAttribute()
效果:
getText() 获取标签元素中的文本
getAttribute() 获取标签元素的 value 值
尝试获取"中国的明天必将更加美好" 和 "百度一下"
尝试两个标签都使用getText来获取他的文本得到
发现无法获取到"百度一下" 这四个字
因为在这个标签中,"百度一下" 属于 value值 ,需要使用 getAttribute() 来获取
也可以理解为 标签中间的文本用 getText()
<a class = "标签里的属性值使用 getAttribute()"> </a>
参数中可以传入该标签的其他属性 比如尝试获取到这个标签中的 submit 也就是 type 的值
三、获取页面标题 和 url
getTitle() 获取页面标题
getCurrentUrl() 获取当前页面url
四、对浏览器窗口进行操作
窗口设置大小
1.窗口最大化
driver.manage().window().maximize();
2.窗口最小化
driver.manage().window().minimize();
3.全屏窗口
driver.manage().window().fullscreen();
4.手动设置窗口大小
driver.manage().window().setSize(new Dimension(1024,2048));
五、对驱动进行操作
1.获取当前页面句柄
driver.getWindowHandle();
2.获取所以页面句柄
driver.getWindowHandles();
3.切换句柄
driver.switchTo().window(w);
用一个例子来解释
要求:①现在要点击百度首页中的 "百度热搜"
②点击 "百度热搜首页" 的"新闻"按钮
代码如下:
运行结果: 页面成功跳转到 "百度热搜" 首页,但点击 “新闻” 按钮失败
原因: 无法定位到 "新闻" 这个按钮
原因:驱动只能指向一个 标签页 进行操作
当前我们创建的驱动是指向的第一个标签页,也就是 "百度首页"
而每个 标签页 都有一个对应的 句柄 用来表示当前标签页
解决方案:①获取当前浏览器的所有标签页的句柄
②使当前驱动指向另一个标签页的句柄(调用switchTo().window()方法,将想要跳转的标签页的句柄传入参数中)
代码:
结果:
六、 获取页面截图
getScreenshotAs() 这个方法由 TakeScreenshot 接口提供
要想要使用这个方法需要将,创建的驱动对象 driver 强转成这个接口类型
参数中可以选择截图的储存类型
效果
每次执行,都会产生一个这样的照片,并且会覆盖上一次的照片
如果想要实现,每次截图的结果都能够保留下来就需要改进一下代码
实现效果: ①每次截图可以放到指定的位置里
②下一张的截图不会覆盖上一张截图(需要提供一个保证名字不会重复的命名方式)
效果演示
将截图的文件 以 **"测试用例方法名-时分秒.png" **的 文件名
存储在 以 "年-月-日" 命名的文件夹下
该文件夹存放在 src 目录下的 image 文件夹中
这样做的好处:
①确保即使是一天内重复跑同一个自动化测试方法,也可以保证当日所有图片不会重名
②可以将截图细分到每一天,某个时间段来区分,方便查看
实现方法
这样就可以在其他自动化测试代码中调用该方法
使用 .getClass().getName() 既可将当前类的名称传入给截图方法
效果:
!!!如果在你的自动化测试代码中,经常有连续截图的场景出现
可以将sim2 的格式改为 HHmmssSS
SS代表毫秒,因为程序的执行速度是很快的一秒内可能会执行很多次截图
就会把这一秒中的所有图片给覆盖掉,所以可以将精度提升到毫秒
或者也可以在两次截图操作之间 加入 Thread.sleep(1000) 来防止覆盖的情况出现
七、关闭单个标签页
//关闭当前标签页
driver.close();
//关闭浏览器 释放driverd对象
driver.quit();
通过一个例子来演示
实现效果:
①:打开百度首页,点击一个热搜跳转到新页面
②:先关闭跳转后页面
③:关闭百度首页
实现方法:
方法一、跳转之后连续调用两次 driver.close()
会出现 noSuchWindowException 异常
原因:之前页面跳转那里说过
driver 对象指向一个标签页
如果需要更换指向标签页需要调用
driver.switchTo().window(handle);
试着想象一下如果不做任何操作直接调用两次 close() 方法
①:首先driver 一直指向的都是 百度首页没有变,第一次百度首页被关闭
②:第二次,此时driver指向的标签页被关闭,也就是driver此时指向的是一个null
如果调用一个null的对象的方法,就会出现异常
方法二、
①:页面跳转前保存 百度首页的 handle
②:页面跳转之后,让driver 指向 新跳转的标签页
③:调用.close()关闭driver 当前指向的标签页
④:让driver指向提前保存的handle,也就是百度首页
⑤:再调用.close()
close() 在关闭浏览器最后一个标签页的时候也会直接将浏览器关闭
适用场景:在需要打开新标签页,并将新标签页关闭,返回的场景下适用
quit()
适用场景:在你想用的场景下
七、等待
有一个场景:
①打开百度首页
②搜索迪丽热巴
③搜索迪丽热巴页面中的 某个 元素
④观察代码异常
代码
结果有两种:
①报异常 noSuchElementException
②无异常
报异常的原因是,前端页面加载需要时间
比如一些css样式的加载比html的内容要慢一点
就会出现当新的页面出来时,代码执行的太快还没等所有内容加载完,代码就跑完了
所以找不到异常
本来我想截一个效果图,奈何校园网太好了快的不行,一下就加载好了跑了十几遍都没报错
所以为了避免上述情况,最好还是在每次有新页面跳转的时候
加上一个 Thread.sleep() 参数单位是ms
我要回去打游戏了明天再写
关于上述问题的延申:
简单复述:
问题:明明页面有这个元素,自动化脚本却报 noSuchElement 异常
可能情况:①页面确实没有该元素
②页面有该元素,代码执行太快,标签还没加载出来
关于以后遇到此类异常,可以考虑以下几种情况排查问题
1.最直接,先加一个等待观察能否解决问题
2.有可能自动化打开的页面和你手动打开的页面不太一样,比如自动化脚本打开的页面都是未登录的页面,而手动打开的页面可能之前登陆过,导致两者之间页面不一样,页面的元素也就不一样
3.页面中直接通过 F12 选择元素复制他的 CSS 或者 Xpath路径默认都是通过标签的 id属性来定位的 就是 #
而,有的页面标签的id是 动态id,每次打开的页面他的id 属性 的值不一样
解决办法:可以直接通过定位该标签的上一级标签,再手动输入该标签 比如
我们可以先复制 div 标签的 css 选择器,再手动添加 a标签
这时候就是通过标签来定位该元素,而不是通过该标签的id属性来定位
!!!等待的分类
强制等待、隐式等待、显示等待
强制等待:
我最喜欢用的就是这个,因为我只会这个
直接阻断程序的运行,就是强制等待
Thread.sleep(ms);
优点:简单方便、效果直接
缺点:极大的增加了自动化代码的执行时间
隐式等待:
一种智能等待,可以规定在查找元素的时候,指定一个时间,
如果期间找到了指定元素 -> 一找到该元素,代码可以立刻往下运行,不在等待
超时之后没找到指定元素 -> 这个时候代码才会报错
可以看到与强制等待不同,这样的等待方式更加灵活,没那么死板,不需要一直等到指定的时间结束
有点像多线程里的 wait() 和notify ,可以理解成只要一找到就立刻唤醒代码继续执行
方法:
driver.manage().timeouts().implicitlyWait();
关于他们直接的调用关系,我就不解释了,因为我也不懂,会用就行嗷
你切记,别管记住什么,你记住了,记住就对了
其实还是要看一点的...
可以看到 implicitlyWait() 的参数 是 Duration 类
延时函数,效果就是延时,所以可以猜测 Duration 类是决定时间单位的一个类
简单看两个Duration 的方法可以了,嗷
以天为单位
以分钟为单位
当然也有秒,毫秒...
直接看写法
喵喵
隐式等待原理:
通过一种轮询的机制,不断地询问是否已经找到该元素
找到了就不再等待执行代码
没找到就接着找接着问
具体的机制比较复杂,我不好打字描述
简单来说
我不会
我只知道是这个机制,喵喵
作用周期:
整个脚本的所以元素,作用于全局
也就是只要你后续代码中有 寻找元素 的操作,他都会给你隐式等待
但是他有一个不好的点:
他只负责判断这个元素存不存在,他并不管你代码执行完了没
举个例子
预期效果:
①找到输入框 输入迪丽热巴
②点击百度一下
隐式等待3s
③查找迪丽热巴页面标签中的 文本 "迪丽热巴" 存入 str 中
④clear()输入框
⑤搜索邓紫棋
⑥查找邓紫棋页面标签中的 文本 "邓紫棋" 覆盖之前 str
⑦输出最终 str
预期效果:输出邓紫棋
邓紫棋 css 标签选择器:
#\31 > div > div > div > div > div > div.cos-row.row-text_1L24W.row_4WY55 > div > div.title-wrapper_XLSiK > a > div > p > span > span
迪丽热巴 css 标签选择器
#\\31 > div > div > div > div > div > div.cos-row.row-text_1L24W.row_4WY55 > div > div.title-wrapper_XLSiK > a > div > p > span > span
这里选择器在页面中属于同一位置,是一样的标签
代码和结果:
结果:迪丽热巴
可以看到这里是不符合预期的
代码大概执行流程
1.我把隐式等待加在最前面,表示这个脚本中所以和 寻找元素 相关的操作 都需要隐式等待3s
2.执行到邓紫棋之前都符合预期
3.从clear开始
4.清空之后执行的 sendKeys("邓紫棋") 和 click() 都经过了隐式等待,以及邓紫棋页面的渲染都经过了隐式等待
5.而,隐式等待只负责判断,要寻找的元素是否存在,一旦存在,代码就会接着往下执行,一直执行到了输出
也就是说, clear 这一步 需要 找到 搜索框
sendkeys 需要 **找到 **搜索框
click 需要 **找到** 百度一下按钮
邓紫棋文本标签 也需要 **找到**
关键就是 隐式等待会 疯狂的往下执行,它比 clear sendkeys click 这三部要执行的快得多,
他只需要知道这些方法需要的标签存在就可以了,不需要等到他们执行完
所以,当他找到 ”邓紫棋“ 这个文本的标签的时候,这个时候 click 还没 执行完,也就是说driver 还停留在了 迪丽热巴的界面
那么此时他就会 直接 获取这个 css 标签,也就是获取的其实还是迪丽热巴的界面的 css 标签
总结:
1.因为查找的 css 标签在 迪丽热巴 页面 和邓紫棋页面 都存在
2.因为隐式等待的判断机制,只需要判断,不需要等到这些代码执行结束再判断下一个,他会一直往下判断,除非遇到找不到的元素才会等待 或 超时报错
解决方法:
可以再查找邓紫棋页面的css 标签之前 加一个强制等待 Thread.sleep() 来保证,是在页面跳转之后才对这个标签进行的隐式等待,并获取
隐式等待总结:
优点:只需要写一次,他往后的driver对象,需要进行 寻找 的代码都要经过隐式等待
缺点:只能作用于查找元素,而且过于死板,每次经过查找元素的代码时都需要进行等待
容易出现预期之外的错误
我又要回去打游戏了喵喵,明天再写
显式等待
和隐式等待一样也是一种,智能等待,既可以在条件通过之后,立即执行后面的代码,不需要一直等到规定时间结束
和隐式等待不同的是,隐式等待只可以判断,元素是否存在
而显示等待,可以对等待的条件,进行设置
比如,元素是否可视,元素是否可点击,元素的某个属性是否为空或等于某个值等等
首先 WebDriverWait 这个对象的创建可以传入两个参数(驱动对象,延迟时间)
再然后调用.until() 在其参数中传入
ExpectedConditions.elementToBeClickble(选择器)
即可完成显示等待的 等待时间设置,成立条件设置
也就是说,隐式等待只关注,该元素是否存在
而显示等待,功能更加强大,可以根据自己的需求来对元素进行条件判断
从代码中也可以看出,显示等待也存在缺点
版权归原作者 Uarecharming 所有, 如有侵权,请联系我们删除。