JS的全称JavaScript,是一种运行在浏览器中的解释型脚本语言,通常用来实现web前端页面的基本功能
Js相对于selenium的控制页面元素,执行速度更快,而且当遇到selenium比较难处理的操纵时,可以考虑使用js代码来实现
在用selenium编写web页面的自动化测试代码时,可能需要执行一些JavaScript代码,selenium本身就支持执行js,我们在代码中可以使用executeScript、executeAsyncScript这两个方法来执行JS。
import org.openqa.selenium.JavascriptExecutor;
executeScript是同步方法,用它执行js代码会阻塞主线程执行,直到JS代码执行完毕;
executeAsyncScript方法是异步方法,它不会阻塞主线程执行。
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript(String script, object... args);
js.executeScript("arguments[0].scrollIntoView(true);",element);
executeScript方法如果有返回值,有以下几种情况:
1、如果返回一个页面元素(document element), 这个方法就会返回一个WebElement
2、如果返回浮点数字,这个方法就返回一个double类型的数字
3、返回非浮点数字,方法返回Long类型数字
4、返回boolean类型,方法返回Boolean类型
5、如果返回一个数组,方法会返回一个List<Object>
6、其他情况,返回一个字符串
7、如果没有返回值,此方法就会返回null
示例:
JavascriptExecutor js = (JavascriptExecutor) driver;
// 用js弹出alert
js.executeScript("alert('Test Case Execution Is started Now..');");
driver.switchTo().alert().accept();
// 用js判断页面加载完毕,返回complete
System.out.println("readyState: "
+ js.executeScript("return document.readyState").toString());
// 用js得到页面的title
String title = (String) js.executeScript("return document.title");
System.out.println("current page title get by js: " + title);
// 用js得到页面的domain name
System.out.println("current page domain name get by js: "
+ js.executeScript("return document.domain"));
// 用js操作页面元素,如高亮显示某个元素
WebElement element = driver.findElement(By.id("kw"));
js.executeScript("arguments[0].setAttribute('style', arguments[1]);",
element, "color: orange; border: 4px solid orange;");
/**
* 每隔一秒check一下页面加载是否完成,check次数是25
*/
public void checkPageIsReady() {
JavascriptExecutor js = (JavascriptExecutor) driver;
for (int i = 0; i < 25; i++) {
if ("complete".equals(js
.executeScript("return document.readyState").toString())) {
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
selenium常用的js总结
http://www.cnblogs.com/tobecrazy/p/4817946.html
前言:做Web自动化时,一般可利用Selenium定位页面元素进行如click,sendKeys类的操作。但也常遇到api没有调用错,却无法定位到元素,或者,无法进行操作。Fortunately,Selenium提供了操作JS的方法:execute_script(),可以直接执行js的脚本。常用的js汇总如下:
一. 控制滚动条高度
问题:需要定位的元素没有在当前页面显示,无法定位,需要上下滑动滚动条才可以看到
--scrollHeight 获取对象的滚动高度。
--scrollLeft 设置或获取位于对象左边界和窗口中目前可见内容的最左端之间的距离。
--scrollTop 设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离。
--scrollWidth 获取对象的滚动宽度。
#滚动到底部
js = "window.scrollTo(0,document.body.scrollHeight)"
#滚动到顶部
js = "window.scrollTo(0,0)"
#横向滚动
1.滚动条左右滚动(一般屏幕最大化后,很少出现此种情况)
2.通过坐标控制横向和纵向滚动条scrollTo(x, y)
js = "window.scrollTo(100,200);"
备注:scrollTo方法无浏览器兼容问题,可以通用,但其他的方法有兼容性区别,如:
1.针对chrome, js = "var q=document.body.scrollTop=0"
2.除chrome其他浏览器,js = "var q=document.documentElement.scrollTop=0"
二. 控制内嵌滚动条高度
问题:在内嵌网页或文本中有滚动条
上下左右滚动
js='document.getElementById("div_id").scrollTop=0’
js='document.getElementById("div_id").scrollTop=10000’
js='document.getElementById("div_id").scrollLeft=0
js='document.getElementById("div_id").scrollLeft=10000’
三.日历控件readonly属性
问题:日历控件存在readonly="readonly"时,无法用Sendkeys输入日期
1.方法:先删除readonly属性,再clear,然后输入
js = 'document.getElementById("date").removeAttribute("readonly");'
2.方法:用js方法输入日期
js2 = 'document.getElementById("date").value="2018-07-20"'
driver.execute_script(js2)
---如果js还是无法滑动滚动条的话,考虑用鼠标操作,ActionChains模拟鼠标的行为
web自动化测试框架selenium调用JavaScript代码常用操作解析
转自: https://blog.csdn.net/cxx654/article/details/79949366
selenium测试框架,selenium框架中的webdriver驱动浏览器模拟人的行为对页面进行操作,开发过程主要可以拆分为以下几个阶段:
a)、web页面加载
b)、定位页面元素
c)、操作页面元素,主要包括文本框输入、鼠标移动、鼠标点击等
d)、判断返回结果
其中最主要的就是 b、c 两步,首先要定位到对应的元素,然后才能对元素进行操作。在selenium中提供了8中元素定位方式,可以通过元素ID号、标签名称、元素name属性、标签文本内容、CSSselector、xpath等方式进行定位
但是,在实际使用中会发现,使用如上方式进行元素操作经常会遇到如下两个问题:
a)、一是代码执行较慢
b)、二是代码执行稳定性不高,待操作的元素明明存在,但可能是由于窗口大小发生变化导致元素位置发生变化,甚至元素重叠的情况,导致代码报错“元素不存在”,或者“元素不在所点击的位置(点击操作有可能被另一个元素所接受)”等莫名其妙的错误,降低了自动化用例执行的稳定性。
针对这种情况,对于自动化代码中不稳定的部分,经常出错的部分,可以将这部分对网页元素进行操作的代码换成对应的JavaScript脚本,由于浏览器原生的支持JavaScript,JavaScript代码直接在浏览器内核中执行,就不会出现元素不在所点击的位置等错误,可以大大提高自动化用例执行的稳定性和执行效率。
下面以使用selenium 调用JavaScript脚本操作百度主页进行示例演示,首先使用selenium打开Chrome浏览器,加载百度主页:
#coding:utf-8
from selenium import webdriver
from time import sleep
url = "http://www.baidu.com"
driver = webdriver.Chrome()
driver.get(url)
driver.implicitly_wait(10)
百度主页关键字输入框和查询按钮的HTML结构如下:
<span class="bg s_ipt_wr quickdelete-wrap">
<span class="soutu-btn" style="display: block;"/>
<input id="kw" class="s_ipt" autocomplete="off" maxlength="255" value="" name="wd"/><!-- 关键字输入框 -->
<a id="quickdelete" class="quickdelete" href="javascript:;" title="清空" style="top: 0px; right: 0px; display: none;"/>
</span>
<span class="bg s_btn_wr">
<input id="su" class="bg s_btn btnhover" type="submit" value="百度一下"/><!-- 查询按钮 -->
</span>
1、输入关键字并点击查询按钮(方法一)
首先使用DOM对象的getElementById方法定位元素,然后给value属性赋值实现关键字输入,然后以同样的方式获取查询按钮对象,并触发按钮的click点击操作。
query = """
var keywordInput = document.getElementById("kw") ; // 根据全局唯一的ID获取输入框对象
keywordInput.value = "selenium" ;
setTimeout(function() {
// 延迟 5 秒点击查询按钮(setTimeout是异步执行)
var queryBtn = document.getElementById("su") ; // 根据全局唯一的ID获取查询按钮对象
queryBtn.click() ;
} , 5000) ;
"""
driver.execute_script(query)
2、输入关键字并点击查询按钮(方法二)
与方法一类似,首先使用DOM对象的getElementById方法定位元素,然后给value属性赋值实现关键字输入,对于查询按钮,也是以同样的方式获取查询按钮对象,但是并不是调用按钮对象的click方法,而是构造一个event事件对象,并将事件对象绑定在查询按钮上实现按钮的点击操作。这样做是因为,有些HTML标签元素没有onclick属性,所以直接调用click方法并不会触发对象的点击操作。
# 方法二(对于没有绑定onclick属性的元素,click方法无效,可以使用dispatchEvent方法)
query = """
var keywordInput = document.getElementById("kw") ; // 根据全局唯一的ID获取输入框对象
keywordInput.value = "selenium javascript" ;
setTimeout(function() {
var queryBtn = document.getElementById("su") ; // 根据全局唯一的ID获取查询按钮对象
var e = document.createEvent("MouseEvents") ; // 创建事件对象
e.initEvent("click" , true , true) ; // 初始化事件对象为 click 事件
queryBtn.dispatchEvent(e) ;
} , 5000) ;
"""
driver.execute_script(query)
3、执行JavaScript脚本返回元素对象 WebElement
使用python调用selenium框架执行JavaScript脚本也可以将JavaScript的执行结果返回给python的一个对象,对象类型是WebElement,只需要在调用的JavaScript脚本中使用return 语句返回对应的内容即可。
# 执行JS脚本返回标签元素对象 WebElement
getKeywordInput = """
var keywordInput = document.getElementById("kw") ;
return keywordInput ;
"""
keywordInputElement = driver.execute_script(getKeywordInput)
keywordInputElement.send_keys("selenium javascript")
4、执行JavaScript脚本在多个相似元素标签中进行过滤,并操作元素标签(点击百度主页的“新闻” 超链接)
百度主页“新闻” 超链接对应的HTML结构如下:
<div id="u1">
<a class="mnav" name="tj_trnews" href="http://news.baidu.com">新闻</a>
<a class="mnav" name="tj_trhao123" href="http://www.hao123.com">hao123</a>
<a class="mnav" name="tj_trmap" href="http://map.baidu.com">地图</a>
<a class="mnav" name="tj_trvideo" href="http://v.baidu.com">视频</a>
<a class="mnav" name="tj_trtieba" href="http://tieba.baidu.com">贴吧</a>
<a class="mnav" name="tj_trxueshu" href="http://xueshu.baidu.com">学术</a>
<a class="lb" οnclick="return false;" name="tj_login" href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F&sms=5">登录</a>
<a class="pf" name="tj_settingicon" href="http://www.baidu.com/gaoji/preferences.html">设置</a>
<a class="bri" style="display: block;" name="tj_briicon" href="http://www.baidu.com/more/">更多产品</a>
</div>
观察以上HTML内容可以发现,只需要将新闻关键字,对所有 a 标签进行搜索即可定位新闻超链接,对应的JavaScript代码如下:
clickNewsLink = """
var linkParentElement = document.getElementById("u1") ; // 获取超链接的HTML父元素节点
var links = linkParentElement.getElementsByTagName("a") ; // 获取linkParentElement元素下的所有超链接
for(var i = 0 ; i < links.length ; i ++) {
// 通过 新闻 关键字过滤需要的超链接
var linkText = links[i].innerHTML.trim() ;
if(linkText.indexOf("新闻") != -1) {
links[i].click() ; // 点击超链接
break ;
}
}
"""
driver.execute_script(clickNewsLink)
5、执行JavaScript脚本下拉浏览器滚动条
# 执行JS脚本操作页面下拉框
scrollScript = """
var keywordInput = document.getElementById("kw") ; // 根据全局唯一的ID获取输入框对象
keywordInput.value = "selenium" ;
setTimeout(function() {
// 延迟 5 秒点击查询按钮(setTimeout是异步执行)
var queryBtn = document.getElementById("su") ; // 根据全局唯一的ID获取查询按钮对象
queryBtn.click() ;
setTimeout(function() {
// document.documentElement.scrollTop = 10000 ; // 适用于除 Chrome浏览器外的其他浏览器
document.body.scrollTop = 10000 ; // Chrome浏览器使用这种方法
} , 5000) ; // 延迟5 秒下拉滚动条到页面最低端
} , 5000) ;
"""
driver.execute_script(scrollScript)
6、在页面众多相似元素中定位需要操作的元素,使用多种条件组合过滤
当页面HTML中存在多个相似的元素标签,很难一次性准确定位时,这时候需要使用一些额外的过滤条件进行判断,常用的过滤条件包括:hasAttribute判断元素是否有某一属性、getAttribute("name") == "XXX"判断元素属性内容是否等于XXX、获取元素标签内容innerHTML并进行判断等。
如下HTML代码中包含两组 a 标签,两组 a 标签对外展示的效果相同,只是当点击第一组链接时会有alert提示框弹出,现在需要使用JavaScript脚本点击第一组 a 标签中的“javascript language"链接,并弹出alert提示框,HTML结构如下:
<html>
<head>
<title>相似标签过滤</title>
</head>
<body>
<h2>Part One</h2>
<div id = "language">
<a name = "python" href="javascript:alert('part one - python')">python language</a><br>
<a name = "java" href="javascript:alert('part one - java')">java language</a><br>
<a name = "C#" href="javascript:alert('part one - C#')">C# language</a><br>
<a name = "scala" href="javascript:alert('part one - scala')">scala language</a><br>
<a name = "javascript" href="javascript:alert('part one - javascript')">javascript language</a><br>
</div>
<h2>Part Two</h2>
<div id = "language">
<a href="javascript:alert('part two - python')">python language</a><br>
<a href="javascript:alert('part two - java')">java language</a><br>
<a href="javascript:alert('part two - C#')">C# language</a><br>
<a href="javascript:alert('part two - scala')">scala language</a><br>
<a href="javascript:alert('part two - javascript')">javascript language</a><br>
</div>
</body>
</html>