【转】 HtmlUnit进行Web自动化测试

HtmlUnit进行Web自动化测试
2008-12-17 10:00

一、HtmlUnit简介

HtmlUnit是Junit 的扩展测试框架之一,该框架模拟浏览器的行为,开发者可以使用其提供的API对页面的元素进行操作,套用官方网站的话HtmlUnit“是Java程序的浏览器”。HtmlUnit支持HTTP,HTTPS,COOKIE,表单的POST和GET方法,能够对HTML文档进行包装,页面的各种元素都可以被当作对象进行调用,另外对JavaScript的支持也比较好。

二、HtmlUnit在实际项目中的应用

在官网上下载最新版本HtmlUnit-2.3.zip,解压缩之后,将jar包添加到自己的测试工程之中。

2.1 载入页面
HtmlUnit已经封装好了HTTP请求的方法,对于请求一个页面,举例如下:

final WebClient webClient = new WebClient();

final HtmlPage page = (HtmlPage) webClient.getPage("http://htmlunit.sourceforge.net");

这就是一类比较常用的形式,WebClient是一个浏览器对象,含有多种浏览器上可进行的操作方法,getPage函数就是通过url取得要访问的页面。getPage返回的文档被转化为HtmlPage对象,也就是被包装为HTML格式的对象,该对象可以输出页面的内容,标题,或者一个表格等等。

在fc-mars具体实施中,将sf-web登录页面url写在外部配置文件中,运行时自动读取url然后载入登录页面

2.2 模拟用户登录
HtmlUnit对js 的支持也不是很完善,有时载入js就会报错,在不影响被测功能的前提下,可以通过client.setJavaScriptEnabled(false) 的方法设置当前js为无效。为了方便模拟用户登录程序的执行,验证码最好设置为一个固定值,剩下的工作就是执行一个POST请求了,代码片段如下:

URL url = new URL("http://www2.baidu.com");

WebRequestSettings reqSet = new WebRequestSettings(url,SubmitMethod.POST);

List reqParam = new ArrayList();

reqParam.add(new NameValuePair("entered_login", username));

reqParam.add(new NameValuePair("entered_password", password));

reqParam.add(new NameValuePair("entered_imagecode", verifycode));

reqSet.setRequestParameters(reqParam);

HtmlPage mypage = (HtmlPage)client.getPage(reqSet);

通过上述代码可以看出对HTTP请求的实现方式,通过SubmitMethod来指定POST或者GET方法类型,将请求的参数赋给WebRequestSettings对象,最后以getPage的方法将请求发送给服务器。

2.3 对Ajax函数的测试

在介绍具体的细节问题之前,先说明下整个测试框架的结构,测试工具一方面是读取case文件,通过自己编写的sql语句从数据源取得期望结果;另一方面将 case文件中的测试数据组装为请求参数,通过HtmlUnit将这些HTTP请求发送给服务器;对Ajax函数的调用,没有通过模拟页面的click事件来进行,而是自定义一些js函数,在js函数中调用被测Ajax函数。

通过编程的方法,并且避过页面的操作来对Ajax进行测试时需要保证Ajax函数改为同步方法,在DWR这种Ajax框架下, DWREngine.setAsync(false)表示该函数是同步的,只有得到服务器回应才执行其后的其他函数。这么做只是为了方便的得到测试执行结果。

自定义的js函数统计写在一个jsp或者html页面中,并将这个页面放在被测程序的服务器目录下,js函数举例如下:

function GetAccocunts() {

DWREngine.setAsync(false);

mtlDWR.GetAccocunts(GetAccocuntsCallback);

}

function GetAccocuntsCallback(data) {

document.getElementById("resultText").value = data.toString();

}

有了上述一段js代码,就可以利用HtmlUnit来进行js函数的执行并从页面元素中得到实际测试结果。代码举例如下:

private String getActResult(HtmlPage page,String jsFunctionStr,String reqParamValue) throws Exception{

page.getElementById("param").setAttribute("value", reqParamValue);

page.executeJavaScript(jsFunctionStr);

String resultStr = page.getElementById("resultText").getAttribute("value").toString();

//得到回调函数的返回值

return resultStr;

}

这段代码中,HtmlPage首先将写满了自定义js函数的页面载入,然后通过getElementById()方法获取页面元素,比如一个,使用这种页面元素作为传递参数的暂存地,并且HtmlPage还有直接运行页面上指定函数名的js函数的作用executeJavaScript(),运行完毕之后,从自定义的页面上取出实际测试结果。

2.4 对HTML元素的操作

对于非Ajax的功能点,会有一些请求的返回结果写在页面的HTML标签内,此时就可以利用HtmlUnit对页面元素的操作来做一些工作。例如一个表单提交之后,返回的结果写在中,取出其中的结果代码如下所示:

//从html标签中的list=取出相应字段

String actResultStr = page.getElementsByTagName("body").item(0).getAttributes().getNamedItem("list").getNodeValue();

page是HtmlPage类的对象实例,HtmlUnit提供很多不同的方法使得开发人员能够获得页面的不同内容,比如常见的得到一个表单,一个锚点,一个元素。如下所示这个类也是从DomNode类继承而来,那么也包含了对XPath的操作。

java.lang.Object

com.gargoylesoftware.htmlunit.html.DomNode

com.gargoylesoftware.htmlunit.SgmlPage

com.gargoylesoftware.htmlunit.html.HtmlPage

在fc系统中,有的页面如编辑页面,载入的数据都是放在一个隐藏的表单之中的,并且UE介入系统开发之后,HTML元素的命名也比较规范,标签的id或者name一般都会存在,所以根据这些可以轻松得到页面内容,如下所示:

resultForm = (HtmlForm?)page.getElementById("ReportSaveForm");

map.put("templateid", resultForm.getInputByName("templateid").getValueAttribute());

map.put("reqsource", resultForm.getInputByName("reqsource").getValueAttribute());

map.put("reporttype", resultForm.getInputByName("reporttype").getValueAttribute());

……
2.5 使用HtmlUnit过程中的一些问题

1. 在DWR Ajax框架下进行HtmlUnit的应用时,jsp页面会引用DWR映射衍生的一些js文件,这些外部js可能会加载失败。此时可以将DWR动态映射产生的js文件保存为静态js文件,在jsp页面内直接引用就能避免这种情况发生。

2. 如果要测试多用户登录系统并进行操作的功能,一种方法是当一个userid的case执行完毕之后,执行一个登出的POST请求,然后重新模拟用户登录;另外一种方法就是重新实例化一个WebClient对象,类似于我们重新打开一个浏览器程序,使得该userid在新的WebClient对象上进行操作。

3. 因为HtmlUnit是基于HTTP请求的,所以开发时需要明确post和get请求的url,比如提交表单的“.do”,以及ajax的函数名,并且还需要明确参数
(转自:xudawei)

你可能感兴趣的:(【转】 HtmlUnit进行Web自动化测试)