您的位置:首页 > Web前端

网页前端持续集成(2) - qunit+JSCoverage+PhantomJS使用小记

2013-12-12 23:42 260 查看
今年早些时候为公司项目做过一些网页前端程序的持续集成(CI),在过去的几个月中不断地给不同的人讲解过之后,我决定开一篇介绍一下。

公司项目是一个ASP.net的网站,其中核心是一些JavaScript 的框架库以及扩展函数。基本目标是在Jenkins上集成单元测试(Unit Test), 和代码覆盖率的统计。由于是前端程序,所以我们采用qunit来做单元测试,代码覆盖率使用JSCoverage(使用简介可移步helloworld)。不过CI需要的是后台自动运行各个步骤,怎么办?我们找到了一个很好用的工具PhantomJS,
它通过一个webkit浏览器内核,实现了后台隐式的打开网址或网页,可以极大的方便前端程序的测试。那么,怎么把这几样宝贝集成起来?这篇介绍的就是这样一个windows上的例子,把它做一遍,可以对这几项工具有基本的了解。

0. 环境搭建

下载qunit, JSCoverage, PhantomJS, ant(apache-ant)。除qunit外,把其余三项的bin目录添加到环境变量Path中去。

用到的压缩包下载地址会列在文末。其解压缩后的根目录列表如下,数目稍多因为把qunit, jscoverage,phantomjs的exe和一些默认配置辅助文件都放过来了,省得来回切换。



1. 定义待测试JavaScript 文件及函数

testme.js:

function add(){
var sum =0;
var count=0;
for (var i=0; i<arguments.length; i++){
if(arguments[i] < 10){
sum += arguments[i];
count++;
}
}
if(count < arguments.length){
for (var i=0; i<arguments.length; i++){
if(arguments[i] >= 10){
sum += arguments[i];
}
}
}
return sum;
}
testme02.js:

function divide(){
if(arguments.length == 0){
return 0;
}
if(arguments[0] == 0)
return 0;
var quotient = arguments[0];
for (var i=1; i<arguments.length; i++){
if(arguments[i] == 0){
continue;
}else{
quotient /= arguments[i];
}
}
return quotient;
}

2. 编辑待测试网页

testme.test.html

<!DOCTYPE html>
<html>
<head>
<!-- we need QUnit as a test runner -->
<link rel="stylesheet" href="qunit.css" type="text/css" media="screen" />
<script src="qunit.js"></script>
<!-- we'd like to have the file we're going to test -->
<script src="testme.js"></script>
<script src="testme02.js"></script>
<script src="test-support.js"></script>
<!-- and finally lets write some tests -->
<script>
test("add(1, 2, 10, 9)", function(){
equal(add(1, 2, 10, 9), 22);
});
test("divide ()", function(){
equal(divide(), 0);
});
test("divide (0, 1, 2)", function(){
equal(divide(0, 1, 2), 0);
});
test("divide (10, 0, 5)", function(){
equal(divide(10, 0, 5), 2);
});
test("add (int, divide())", function(){
equal(add(1, divide(12, 3)), 5);
});
</script>
<style>
.code {
white-space: pre;
font-family: courier new;
width: 100%;
}

.miss {
background-color: #FFFFFF;
}

.hit {
background-color: #94FF7C;
}

.undef {
background-color: #00FF9E;
}
</style>
</head>
<body>
<h1 id="qunit-header">QUnit Tests</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
</body>
</html>


其中写了5个测试用例,并加载了qunit.js

3.在build.xml中定义目录结构。

<project name="jsunittests" basedir="." default="main">
<property name="basedir" location="."/>
<property name="builddir" location="${basedir}/target"/>
<proerty name="jstestdir" location="${builddir}/testjs"/>
<property name="jsdir" location="${jstestdir}/js"/>
<property name="jsinstrumenteddir" location="${jstestdir}/jsinstrumented"/>
<property name="testhtmdir" location="${builddir}/testhtm"/>
<condition property="phantom.filename" value="phantomjs.bat"><os family="windows"/></condition>
<property name="jscoverage.filename" value="jscoverage.bat"/>
...
</project>
$basedir 是当前目录,$jstestdir下的两个目录存放待测试js文件,其中\js是原始文件,\jsinstrumented是经过JSCoverage注入过锚标记的文件。$testhtmdir是测试用的HTML目录。

4.在build.xml中定义各项任务



任务clean是清空全部已有文件,prep是准备工作,把所有用到的文件拷贝到目标目录中去。

<target name="clean">
<delete dir="${builddir}"/>
</target>
<target name="prep">
<mkdir dir="${builddir}"/>
<mkdir dir="${jstestdir}"/>
<mkdir dir="${jsdir}"/>
<mkdir dir="${jsinstrumenteddir}"/>
<mkdir dir="${testhtmdir}"/>
<!--copy test source js files to target-->
<copy todir="${jsdir}">
<fileset dir="${basedir}">
<include name="testme.js" />
<include name="testme02.js" />
</fileset>
</copy>
<!-- run jscoverage to produce a version of the file instrumented for code coverage -->
<exec executable="${jscoverage.filename}" failonerror="true">
<arg value="${jsdir}"/>
<arg value="${jsinstrumenteddir}"/>
</exec>
<!-- copy our test htm files and modify them to point to the coverage indexed version of the test file. -->
<copy todir="${testhtmdir}">
<fileset dir="${basedir}">
<include name="*.test.html" />
</fileset>
</copy>
<!-- copy core resources to testhtmdir so we can load them with same paths as when executing test htm files directly -->
<copy todir="${testhtmdir}">
<fileset dir="${jsinstrumenteddir}">
<include name="**/*.js" />
<exclude name="jscoverage.js"/>
</fileset>
</copy>
<copy todir="${testhtmdir}">
<fileset dir="${basedir}">
<include name="test-support.js" />
<include name="run-qunit.js" />
<include name="qunit.css" />
<include name="qunit.js" />
</fileset>
</copy>
</target>
接下来,定义实际做测试的任务jstest。我们用PhantomJS打开一个HTML文件,这个html包含qunit文件,并调用已经带有JSCoverage标记的JS待测试函数。这样如果运行成功,我们可以得到测试例子的通过率和代码覆盖率。

<target name="jstest">
<!--Run all tests via phantom, fail if tests fail. Execute all files with extension .test.htm. -->
<apply executable="${basedir}/${phantom.filename}" failonerror="true" dir="${testhtmdir}" relative="false">
<arg value="run-qunit.js"/>
<srcfile/>
<!--arg[0]-->
<fileset dir="${testhtmdir}">
<include name="*.test.html" />
</fileset>
<!--argp[1]-->
<arg value="${basedir}"/>
</apply>
</target>
这里的run-qunit.js是PhantomJS的启动文件,它从中得知该从哪个网址/网页启动,导入后又该执行什么动作。之后的第一个参数是输入的网页文件,第二个参数是输出路径。

到目前为止,各项任务定义完毕,可以调用了。

<target name="main" depends="clean, prep, jstest">
</target>

5. 编辑jscoverage.bat

注意定义成本地的绝对路径。最后一行的末尾 %* 意思是接受后续的参数。

set JSCov_Dir=D:\Product\VEF-CI-ref\jsunit\
%JSCov_Dir%\jscoverage.exe %*


6. 编辑phantomjs.bat

set PhantomJS_Dir=D:\Product\VEF-CI-ref\jsunit\
%PhantomJS_Dir%/phantomjs.exe %*


7. 编辑run-qunit.js

这个文件告诉PhantomJS如何启动。最重要的是要定义onReady函数,在网页启动完成后执行。这里我们仅仅基于JSCoverage的各行执行次数,计算了总的文件覆盖率。

额外的还有test-support.js文件,定义了一些辅助函数。因这两文件较长,此处就不列了,文件细节可以在压缩包中找到。

8.执行ant

运行成功的输出如下,注意到这里两个文件的覆盖率均为100%。






9.检查输出网页

打开.\target\testhtm\testme.test.html,可以看到qunit的执行结果。



打开.\target\testhtm\testme.coverage.testme.js.html,能够看到以不同颜色标示的代码覆盖部分。怎么样?还算清楚吧:)有同学可能注意到了,这些颜色就是在testme.test.html中<style>部分定义的。



当然 testme.coverage.testme02.js.html也能带来同样的显示。

小结:

1. qunit+JSCoverage+PhantomJS 的组合能够满足前端程序对于持续集成的基本需要。对于目标程序,其开发语言限制较少,比如Java完全可以。

2. 如果想要集成到Jenkins的平台中,只需要将JSCoverage, PhantomJS等执行步骤单独设置成Jenkins的一个任务即可。

3. 如果想把相应的测试结果,代码覆盖率等输出到文件,可以编辑PhantomJS.exe 后紧跟的第一个文件,比如这里的run-qunit,js,在onReady()函数中加入你所需要的部分。

注:压缩包下载地址phantomjs-jscoverage.zip
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: