出品|51Testing软件测试网
Selenium WebDriver让我们轻松实现与浏览器的交互,通过页面元素定位、执行对应的元素操作及断言设置,这一系列的步骤开启了Web自动化脚本的创建。
相信大家对于元素定位及其执行并不陌生,今天我们就来聊一聊Selenium WebDriver中另一大特色JS语句的执行,即JavaScriptExecutor。
◆ ◆ ◆ ◆ ◆
什么是JavaScriptExecutor
JavaScriptExecutor 是Selenium WebDriver提供的一个接口,它提供了一种通过WebDriver直接执行JavaScript的方式,在选定窗口或当前页面上运行 JavaScript 的方法。
如果你用的是Java语言,那么可以通过导入“org.openqa.selenium.JavascriptExecutor” 直接使用它;如果你用的是Python,那就更方便了,直接“from selenium import webdriver”即可。
◆ ◆ ◆ ◆ ◆
为什么在Selenium中
使用JavaScriptExecutor
通常情况下我们会使用各种Web定位器来定位页面元素,例如id、name、XPath等。
但是如果这些定位器无法按预期工作,定位不到对应的元素,这时我们就可以通过JavaScriptExecutor来尝试解决这类问题。
同理,当我们对页面上某个元素执行点击操作时,最常见的就是driver.findElement(By.id(“button”)).click()。
但是click()方法并非适用于所有Web浏览器,有时同一个Web控件在不同浏览器上的行为也有可能不同。
为了应对这类情况,JavaScriptExecutor同样是一个最优的解决方案,因为JS语句本身就是Web脚本语言,用来控制网页行为。
◆ ◆ ◆ ◆ ◆
Selenium中使用JavaScriptExecutor场景介绍
点击按钮
方法一:
-
Python版
driver.execute_script("document.getElementById('XXX').click()")
(左右滑动查看完整代码)
-
Java版
js.executeScript("document.getElementById('XXX').click();");
(左右滑动查看完整代码)
方法二:
-
Python版
driver.execute_script("arguments[0].click()",button)
(左右滑动查看完整代码)
-
Java版
js.executeScript("arguments[0].click();", button);
(左右滑动查看完整代码)
方法二中的arguments指的是execute_script()方法中js代码后面的所有参数,arguments[0]表示第一个参数,argument[1]表示第二个参数。
在不使用sendKeys()方法的情况下
在文本框中键入文本
-
Python版
driver.execute_script("document.getElementById('XXX').value='someValue' ")
(左右滑动查看完整代码)
-
Java版
js.executeScript("document.getElementById('XXX').value='someValue';");
(左右滑动查看完整代码)
通过值传递“真”|“假”来处理复选框
-
Python版
driver.execute_script("document.getElementById('XXX').checked=false")
(左右滑动查看完整代码)
-
Java版
js.executeScript("document.getElementById('enter element id').checked=false;");
(左右滑动查看完整代码)
在Selenium WebDriver中
生成Alert弹框
-
Python版
driver.execute_script("alert('注册成功');")
(左右滑动查看完整代码)
-
Java版
js.executeScript("alert('注册成功');");
(左右滑动查看完整代码)
使用Javascript刷新浏览器窗口
-
Python版
driver.execute_script("history.go(0)")
(左右滑动查看完整代码)
-
Java版
js.executeScript("history.go(0)");
(左右滑动查看完整代码)
获取网页标题
-
Python版
driver.execute_script("return document.title")
(左右滑动查看完整代码)
-
Java版
js.executeScript("return document.title;").toString();
(左右滑动查看完整代码)
获取当前域名
-
Python版
driver.execute_script("return document.domain")
(左右滑动查看完整代码)
-
Java版
js.executeScript("return document.domain;").toString();
(左右滑动查看完整代码)
实现页面滚动效果
-
Python版
# 通过JS进行页面滚动至末尾
driver.execute_script("window.scrollBy(0,document.body.scrollHeight)")
# 通过JS进行页面回滚至开始
driver.execute_script("window.scrollBy(0,-document.body.scrollHeight)")
(左右滑动查看完整代码)
-
Java版
# 通过JS进行页面滚动至末尾
js.executeScript(“window.scrollBy(0,document.body.scrollHeight)”);
# 通过JS进行页面回滚至开始
js.executeScript(“window.scrollBy(0,-document.body.scrollHeight)”);
(左右滑动查看完整代码)
获取整个页面的内容
-
Python版
driver.execute_script(return document.documentElement.innerText)
(左右滑动查看完整代码)
-
Java版
js.executeScript(" return document.documentElement.innerText;").toString();
(左右滑动查看完整代码)
◆ ◆ ◆ ◆ ◆
Demo实战演练
我们以“大众点评”,通过Selenium Python+JavaScriptExecutor进行多版本迭代实战演练,获取首页网红餐厅信息。
测试场景1
不通过JavaScriptExecutor,使用常规元素定位及操作实现:
(1) 通过Chrome浏览器,打开“大众点评”主页;
(2) 定位搜索框,搜索“网红餐厅”;
(3) 获取首页搜索结果中的全部餐厅名称;
(4) 获取获取首页“有团购”的餐厅名称;
(5) 获取获取首页“可订座”的餐厅名称;
(6) 关闭浏览器。
测试脚本实现
(1)相关库的导入;
(2)初始化Chrome驱动,开启大众点评首页,且窗口最大化;
(3)通过ID定位搜索框,搜索“网红餐厅”;
(4)这时由于搜索结果显示页面属于新开启的页面,我们需要切换到当前页面窗口;
(5)获取首页搜索结果中的所有“网红餐厅”名称;
通过观察发现,首页中显示的餐厅共有15个,并且餐厅名称的XPath都有固定的规则,仅通过li的下标值的递增。
第一个餐厅名称的XPath:
//*[@id="shop-all-list"]/ul/li[1]/div[2]/div[1]/a/h4
(左右滑动查看完整代码)
最后一个餐厅名称的XPath:
//*[@id="shop-all-list"]/ul/li[15]/div[2]/div[1]/a/h4
(左右滑动查看完整代码)
所以通过range(1,16)循环获取当前页面上15个餐厅的名称:
(6)获取获取首页前5个“有团购”的餐厅名称;
(7)获取获取首页前5个“可订座”的餐厅名称;
(8)关闭退出。
运行结果
测试场景2
通过JavaScriptExecutor实现上述场景。基于场景1,本场景中还增加演示通过JS获取页面标题、当前域名、执行页面滚动操作,实现Alert弹框操作效果。
测试脚本实现
(1)相关库的导入;
(2)初始化Chrome驱动,开启大众点评首页,且窗口最大化;
(3)通过JS在文本框中输入“网红餐厅”,通过JS执行搜索;
(4)同场景一,需要切换到当前页面窗口(结果展示窗口);
(5)通过执行JS,进行页面滚动操作,查看当前页面中的餐厅信息;
(6)获取首页搜索结果中的所有“网红餐厅”名称;
我们直接从页面获取餐厅名称JS Path,通过观察发现,不难发现首页餐厅名称的JS Path也是有规律的,仅通过li:nth-child的下标值的递增。
第一个餐厅名称的JS Path:
document.querySelector("#shop-all-list > ul > li:nth-child(1) > div.txt > div.tit > a > h4")
(左右滑动查看完整代码)
最后一个餐厅名称的JS Path:
document.querySelector("#shop-all-list > ul > li:nth-child(15) > div.txt > div.tit > a > h4")
(左右滑动查看完整代码)
在定位到元素后,我们需要获取该元素的文本信息,通过JS语句获取餐厅名称元素的文本信息方式如下:
return document.querySelector('#shop-all-list > ul > li:nth-child(1) > div.txt > div.tit > a> h4').innerText
(左右滑动查看完整代码)
由于querySelector()中的字符串内容比较长,建议将上面的JS命令进行拆分:
style = "#shop-all-list > ul > li:nth-child(1) > div.txt > div.tit > a> h4"
js_style = "return document.querySelector(" + "'" + style + "'" + ").innerText"
(左右滑动查看完整代码)
下面我们同样结合range(1,16)循环获取当前页面上所有餐厅的名称:
(7)获取获取首页前5个“有团购”的餐厅名称,同理,我们通过定位“有团购”勾选框,获取其JS Path;
document.querySelector
("body > div.section.Fix.J-shop-search >
div.content-wrap > div.shop-wrap > div.content > div.filter-box.J_filter_box >
div.filt-classify > a:nth-child(1) > i.icon-check")
(左右滑动查看完整代码)
获取前5个“有团购”餐厅名称代码如下:
(8)获取获取首页前5个“可订座”的餐厅名称,同理,我们通过定位“可订座”勾选框,获取其JS Path;
document.querySelector
("body > div.section.Fix.J-shop-search >
div.content-wrap > div.shop-wrap > div.content > div.filter-box.J_filter_box >
div.filt-classify > a:nth-child(2) > i")
(左右滑动查看完整代码)
获取前5个“可订座”餐厅名称代码如下:
(9)通过JS获取当前页面标题;
(10)通过JS获取当前域名;
(11)通过JS以弹框形式显示“查询成功”消息;
(12)关闭退出。
运行结果
测试场景3(优化)
从场景2中可以看出,有三次都在获取当前页面中的餐厅名称,且获取名称所用到的JS代码非常相似,可见代码存在冗余情况。
为了后期能够有效维护代码,我们可以将获取餐厅名称的脚步单独拿出来,作为一个函数,每次需要的时候直接调用即可。
对需要重复使用的方法进行函数封装:
完整代码如下:
◆ ◆ ◆ ◆ ◆
总结
JavaScriptExecutor让我们能够通过WebDriver在网页上执行JavaScript代码,在传统定位方式失效或者某些浏览器下元素执行方式失效的情况下,JavaScriptExecutor不失为一个最优的备选方案。在同等情况下,它还能使自动化脚本更高效地执行。
以上为大家分享了如何在Selenium WebDriver中使用JavascriptExecutor,通过对JavascriptExecutor常用方法的介绍,并结合具体场景演示了JS在Selenium WebDriver中的实际应用,希望能够给大家的测试工作带来帮助,感兴趣的读者不妨一试。
◆ ◆ ◆ ◆ ◆
End
点击阅读☞这些大厂的内推高薪职位,一定不能错过!
点击阅读☞功能测试进阶,记一次简单的性能测试实践
文章评论