前端自动化的单元测试JsTestDriver+Jasmine.docx

上传人:b****7 文档编号:10474091 上传时间:2023-02-13 格式:DOCX 页数:22 大小:486.83KB
下载 相关 举报
前端自动化的单元测试JsTestDriver+Jasmine.docx_第1页
第1页 / 共22页
前端自动化的单元测试JsTestDriver+Jasmine.docx_第2页
第2页 / 共22页
前端自动化的单元测试JsTestDriver+Jasmine.docx_第3页
第3页 / 共22页
前端自动化的单元测试JsTestDriver+Jasmine.docx_第4页
第4页 / 共22页
前端自动化的单元测试JsTestDriver+Jasmine.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

前端自动化的单元测试JsTestDriver+Jasmine.docx

《前端自动化的单元测试JsTestDriver+Jasmine.docx》由会员分享,可在线阅读,更多相关《前端自动化的单元测试JsTestDriver+Jasmine.docx(22页珍藏版)》请在冰豆网上搜索。

前端自动化的单元测试JsTestDriver+Jasmine.docx

前端自动化的单元测试JsTestDriver+Jasmine

自动化的单元测试

采用Jasmine进行单元测试有个问题就是需要一个html来加载源代码和测试代码,测试的时候在浏览器中手动的打开这个html。

下图中是test.html。

那如果有10个test.html,需要在5种浏览器中进行测试,那就必须打开50次。

这个工作量还是很大的。

那如何可以做到有脚本去进行自动化的单元测试呢?

JsTestDriver可以做到。

JsTestDriver档案

∙用途:

javascript单元测试框架

∙下载:

∙使用文档:

JsTestDriver是一个JavaScript单元测试工具,易于与持续构建系统相集成并能够在多个浏览器上运行测试轻松实现TDD风格的开发。

当在项目中配置好js-test-driver以后,如同junit测试java文件一般,js-test-driver可以直接通过直接运行js文件,来对js文件单元测试。

下图是JsTestDriver的架构:

捕获不同的浏览器之后,服务器会负责将JavaScript测试用例运行程序代码加载到浏览器中。

可以通过命令行捕获浏览器,也可以通过将浏览器指向服务器URL来捕获浏览器。

一旦捕获到浏览器,该浏览器就被称为从属浏览器。

服务器可以加载JavaScript代码,在每个浏览器上执行测试用例,然后将结果返回给客户端。

客户端(命令行)需要以下两个主要项目:

JavaScript文件,即源文件和测试文件

配置文件,用于组织源文件和测试文件的加载

这个架构比较灵活,允许单个服务器从网络中的其他机器捕获任意数量的浏览器。

例如,如果您的代码在Linux上运行但您想针对另一个Windows机器上的MicrosoftInternetExplorer运行您的测试用例,那么这个架构很有用。

Jasmine+JsTestDriver

采用Jasmine编写单元测试代码,JsTestDriver作为自动化测试的平台,在多浏览器下进行自动化测试。

从简单例子开始

∙新建名为simply的工程

∙下载最新的Jasmine

copy下图文件到simply/lib下,实际上只使用到了jasmine.js

∙下载最新的JsTestDriver

将JsTestDriver-1.3.4.b.jar放到simply目录下。

∙下载Jasmine对JsTestDriver的适配器

copyJasmineAdapter.js到simply/lib目录下

∙编写js源代码和单元测试代码

src/person.js代码:

∙functionPerson(name,age){

∙this.name=name;

∙this.age=age;

∙}

∙Person.prototype.getName=function(){

∙returnthis.name;

∙}

∙Person.prototype.getAge=function(){

∙returnthis.age;

∙}

spec/person.spec.js代码:

describe('PersonClassTest',function(){

varperson=newPerson('Colin',31);

it('shouldbeworkableforgetName',function(){

expect(person.getName()).toEqual('Colin');

});

it('shouldbeworkableforgetAge',function(){

expect(person.getAge()).toEqual(31);

});

});

∙在simply目录下建配置文件,jsTestDriver.conf内容如下:

∙server:

http:

//localhost:

9876

∙load:

∙-lib/jasmine.js

∙-lib/JasmineAdapter.js

∙-src/person.js

∙test:

∙-spec/person.spec.js

∙server:

服务器路径

∙load:

依赖脚本

∙test:

测试脚本

具体的配置参数,参考官方说明

∙在simply目录下建server.bat文件,内容如下:

java-jarJsTestDriver-1.3.4.b.jar–port9876–browser“[测试机上的IE路径]“,”[测试机上的Firefox路径]“,”[测试机上的Chrome路径]“,”[测试机上的Safari路径]“

这个例子中用了下面脚本:

java-jarJsTestDriver-1.3.4.b.jar–port9876–browser“C:

\Users\jianfei.jujf\AppData\Local\MozillaFirefox\firefox.exe”

更多命令参考官方文档

∙在simply目录下建run.bat文件,内容如下:

java-jarJsTestDriver-1.3.4.b.jar–testsall>d:

\result.txt

更多命令参考官方文档

最后,先运行server.bat,其实就是启动了一个JsTestDriver的服务器,脚本会把浏览器打开,浏览器打开后,运行run.bat,单元测试代码就开始运行了,并生成测试结果。

注意,jsTestDriver是基于Java的,所以要先确保运行bat脚本的机器已经安装了java,并且配置了环境变量。

settingrunnermodeQUIET

..

Total2tests(Passed:

2;Fails:

0;Errors:

0)(1.00ms)

Firefox12.0Windows:

Run2tests(Passed:

2;Fails:

0;Errors0)(1.00ms)

jsTestDriver采用自己的测试界面,并没有像jasmine那样采用一个html来作为测试入口,来加载js源代码,测试用例和显示测试结果。

那如果有dom操作,以及dom事件相关的单元测试怎么办?

接着看下面如何解决dom依赖以及事件模拟问题。

解决dom依赖

JsTestDriver采用了自己的测试界面,那要解决dom依赖问题,那就要把测试依赖的html片段加到JsTestDriver的片段中。

思路:

采用同步的ajaxcall把html片段读取到测试端浏览器,避免异步请求等待。

读取html片段后,放入一个div容器,将div容器append到jsTestDriver的测试页面中。

根据这个思路,编写了jasmine-fixture.js,代码如下:

(function(){

vardefaultConfig={

wrapperHook:

'J_JF',

/**

*html片段插入dom的容器id

*/

wrapperTpl:

'${fixture}

',

/**

*数据缓存

*/

/**

*html片段存放的目录路径

*/

path:

'/test/'

};

functionFixture(config){

this.wrapperHook=defaultConfig.wrapperHook||config.wrapperHook;

this.wrapperTpl=defaultConfig.wrapperTpl||config.wrapperTpl;

this.path=defaultConfig.path||config.path;

}

Fixture.prototype={

constructor:

Fixture,

load:

function(){

varsHtml;

if(arguments.length){

sHtml=this.read.apply(this,arguments);

this._appendTo(sHtml);

}

},

read:

function(){

varurls=arguments,

aHtml=[],

len=urls.length,

i=0;

if(len){

for(;i

aHtml.push(this._getHtml(urls[i]));

}

}

returnaHtml.join('');

},

_substitute:

function(str,obj){

str=str||"";

returnstr.replace(/\\?

\$\{([^{}]+)\}/g,function(match,key){

if(match.charAt(0)=="\\"){

returnmatch.slice

(1);

}

return(obj[key]!

==undefined)?

obj[key]:

"";

});

},

_createXHR:

function(){

varxhrObj;

if(window.XMLHttpRequest){

try{

xhrObj=newXMLHttpRequest();

}catch(e){

}

}elseif(window.ActiveXObject){

try{

xhrObj=newActiveXObject("Msxml2.XMLHTTP");

}catch(e){

try{

xhrObj=newActiveXObject("Microsoft.XMLHTTP");

}

catch(e){

}

}

}

returnxhrObj;

},

_getHtml:

function(url){

var_this=this,

sHtml,

path=_this.path,

sUrl=path.match('/$')&&path+url||path+'/'+url,

xhrObj=_this._createXHR();

if(xhrObj){

try{

xhrObj.open('GET',sUrl,false);

xhrObj.onreadystatechange=function(){

if(xhrObj.readyState===4){

if(xhrObj.status===200){

sHtml=xhrObj.responseText;

}

}

};

xhrObj.send(null);

}catch(e){

//Handleerror

}

}

returnsHtml;

},

_appendTo:

function(html){

vardoc=document,

oDiv,

wrapperTpl=this.wrapperTpl,

wrapperHook=this.wrapperHook,

oWrapper,

wrapperedHtml;

if(html){

oWrapper=doc.getElementById(wrapperHook);

if(oWrapper){

oWrapper.innerHMTL=html;

}else{

oDiv=doc.createElement('div');

wrapperedHtml=this._substitute(wrapperTpl,{

'fixture':

html

});

oDiv.innerHTML=wrapperedHtml;

doc.body.appendChild(oDiv.children[0]);

oDiv=null;

}

}

},

clean:

function(){

varoWrapper=doc.getElementById(this.wrapperHook);

if(oWrapper){

oWrapper.innerHTML='';

}

}

};

jasmine.Fixtures=Fixture;

jasmine.getFixtures=function(){

returnjasmine._currentFixtures_=jasmine._currentFixtures_||newjasmine.Fixtures();

};

})();

window.JF={};

beforeEach(function(){

JF=newjasmine.getFixtures();

});

如何使用?

看下面列子:

src/dom.js代码:

(function(){

vardoc=document;

varDom={

byId:

function(id){

returndoc.getElementById(id);

},

byTag:

function(tagName){

returndoc.getElementsByTagName(tagName);

}

};

window.Dom=Dom;

})();

src/dom.spec.js代码:

describe('DomClassTest',function(){

varurl1='test.html';

beforeEach(function(){

JF.load(url1);

});

it('shouldgetthecorrectdomnodebybyId',function(){

expect(Dom.byId('test')).not.toBeNull();

});

it('shouldgetthecorrectdomnodesbybyTag',function(){

vardEms=Dom.byTag('em');

expect(dEms).not.toBeNull();

expect(dEms.length===2).toBeTruthy();

});

});

spec/fixtures/test.html代码:

更改配置文件jsTestDriver.conf:

server:

http:

//localhost:

9876

load:

-lib/jasmine.js

-lib/JasmineAdapter.js

-lib/jasmine-fixture.js

-src/person.js

-src/dom.js

test:

-spec/person.spec.js

-spec/dom.spec.js

serve:

-spec/fixtures/*.html

注意:

这个参数是serve不是配置服务器的server。

上面的配置,会加载spec/fixtures/下的所有html文件,对应的路经是在test目录下,也就是说路径应该是“http:

//localhost:

9876/test/spec/fixtures/test.html”

启动server.bat,浏览器打开后,运行run.bat,查看结果如下,说明测试通过。

settingrunnermodeQUIET

....

Total4tests(Passed:

4;Fails:

0;Errors:

0)(24.00ms)

Firefox12.0Windows:

Run4tests(Passed:

4;Fails:

0;Errors0)(24.00ms)

查看JsTestDriver的测试页面dom结构,请看下图,html片段确实已经被插入到测试页面。

事件模拟

YUI已经实现了事件模拟,但作为测试框架,应该依赖于具体的一个js框架。

也就是说,事件模拟的实现不能依赖YUI。

这个工作玉伯已经在kissy里做了,直接拿kissy里的事件模拟的js.

如何使用?

看下面例子:

src/dom.spec.js代码:

describe('EventsimulateTest',function(){

varurl1='spec/fixtures/test.html';

beforeEach(function(){

JF.load(url1);

});

it('cantriggerclickevent',function(){

vari=0,

dTest=Dom.byId('test');

dTest.onclick=function(){

i++;

};

jasmine.simulate(dTest,'click');

expect(i===1).toBeTruthy();

});

});

更改配置文件jsTestDriver.conf:

server:

http:

//localhost:

9876

load:

-lib/jasmine.js

-lib/JasmineAdapter.js

-lib/jasmine-fixture.js

-lib/event-simulate.js

-src/person.js

-src/dom.js

test:

-spec/person.spec.js

-spec/dom.spec.js

serve:

-spec/fixtures/*.html

运行结果:

settingrunnermodeQUIET

.....

Total5tests(Passed:

5;Fails:

0;Errors:

0)(10130.00ms)

Firefox12.0Windows:

Run5tests(Passed:

5;Fails:

0;Errors0)(10130.00ms)

代码覆盖率

单元测试的时候,代码覆盖率是个非常重要的指标。

JsTestDriver中增加代码覆盖率统计的功能也是非常简单的。

∙下载目前最新的coverage-1.3.4.b.jar,copy到simply目录下。

∙在jsTestDriver.conf文件里增加配置项

∙plugin:

∙-name:

"coverage"

∙jar:

"coverage-1.3.4.b.jar"

∙module:

"com.google.jstestdriver.coverage.CoverageModule"

运行单元测试代码看运行结果:

Total5tests(Passed:

5;Fails:

0;Errors:

0)(33.00ms)

Firefox12.0Windows:

Run5tests(Passed:

5;Fails:

0;Errors0)(33.00ms)

D:

\eclipse-indigo\workspace\simple\.\spec\person.spec.js:

100.0%covered

D:

\eclipse-indigo\workspace\simple\.\spec\dom.spec.js:

100.0%covered

D:

\eclipse-indigo\workspace\simple\.\lib\jasmine.js:

47.826088%covered

D:

\eclipse-indigo\workspace\simple\.\lib\JasmineAdapter.js:

64.83517%covered

D:

\eclipse-indigo\workspace\simple\.\lib\jasmine-fixture.js:

85.0%covered

D:

\eclipse-indigo\workspace\simple\.\lib\event-simulate.js:

28.947369%covered

D:

\eclipse-indigo\workspace\simple\.\src\person.js:

100.0%covered

D:

\eclipse-indigo\workspace\simple\.\src\dom.js:

100.0%covered

HOZ框架单元测试

前面通过简单的例子,已经展示了如何采用Jasmine+JsTestDriver来构建一个自动化的单元测试解决方案。

但对于相对复杂的HOZ框架,要如何做呢?

∙在HOZ目录下新建jsTestDriver文件夹

∙将Jasmine,JsTestDriver相关的JS,Jar,conf,bat文件放在jsTestDriver文件夹中

∙为不同的module编写独立的conf和bat文件

HOZ框架中有lang,ua,core,dom等模块,每个模块都有独立的源代码和测试文件。

在项目中,也是由不同的人负责不同的业务单元进行独立开发,如何做到所有的单元测试只有一个脚本启动入口,进行自动化的单元测试呢?

JsTestDriver在这个方面提供了很好的支持。

从上面截图中,可以看到有run-{moduleName}.bat和jsTestDriver-{moduleName}.conf对应。

以run-core.bat为例,这个文件的脚本是这样的:

∙java-jarjsTestDriver-1.3.4.b.jar--basePath..--reset--runnerModeINFO--configjsTestDriver-core.conf--testsall>>result.txt

其中有个重要的配置是basepath,为什么要增加这个配置呢?

因为jsTestDriver进行单元测试的时候,其实是起了一个webserver,这个server的contextpath所对应目录是jsTestDriver-1.3.4.b.jar所在目录,在HOZ框架的测试中对于是jsTestDriver目录。

而js源代码,单元测试的代码分别放在与jsTestDriver同级的build,test目录中。

如果不在basepath设定为比jsTestDriver,build和test目录层级更高的目录,jsTestDriver是没法取到js源代码和测试代码的。

basePath也可以在conf文件里设定,但从试验的结果看,在conf文件里用相对路径有问题,所以把b

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 军事

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1