CruiseControl 小结
持续集成(ContinuousIntegration)可能对不熟悉自动化测试的部分人来说是一个新鲜词,然而它在软件开发,特别是大型的开发任务过程中,正在发挥越来越大的作用。
软件开发为了保证代码的稳定和可用,测试是必不可少的,没有哪个公司和个人敢说自己的代码100%没有BUG。在软件测试这一块,很多企业是招专门的测试工程师进行人工测试。人工测试有自己的特有的优点,但自动化测试也有自己的好的一面。
1)节约测试的人力成本
2)测试点全面,可能人有时候会忘记要对哪些点做测试,但机器不会忘记。
3)如果代码有BUG,它可以即时提供精确的日志信息和错误报告邮件发给开发者,实现错误的即时,精准定位。
4)有的测试可能人工没法完成,如对网站进行高并发访问的压力测试。
CruiseControl:简称CC,持续集成工具,主要提供了基于版本管理工具(如CVS、VSS、SVN)感知变化或每天定时的持续集成,并提供持续集成报告、Email、Jabber等等方式通知相关负责人,其要求是需要进行日构建的项目已编写好全自动的项目编译脚本(可基于Maven或Ant)。
我这段时间一直在做CC的搭建工作,在不同的平台下(windows32,windows64,linux32,linux64),现在做一个小结。
第一步:安装CC
我现在使用的CC版本是2.8.3,可能在这之前你需要安装jdk,svnclient,ant.
第二步:配置CC
启动CC的入口程序windows下是cruisecontrol.bat,linux下是cruisecontrol.sh
CC启动的时候会将配置文件以参数的方式传递给它,也可以使用默认的配置文件文件名config.xml,就像ant命令的默认配置文件是执行命令的目录下的build.xml一样。
CCconfig.xmlSample:
css="${CC.root}\cc-bin\windows\webapps\cruisecontrol\css\cruisecontrol.css"
xsldir="${CC.root}\cc-bin\windows\webapps\cruisecontrol\xsl"
charset="utf-8"
logdir="${CRUISE_WORKSPACE}\logs\${project.name}">
当不同的项目均需要Junit测试时,可以把它们配置在同一个build.xml中,但它们的程序依赖,目录结构,业务功能可能不一样,而且testcase数据可能很多,所以有必要将它们的JunitTesttask放在各自的anttask里面(即在build.xml配置batchtest)。
但由于生成Junit的日志文件(.xml格式)是CC的内置支持功能,在没有找到CC的这部分代码的情况下,想到了另外一个解决方案。对CC生成的Junit日志文件进行修改,给Junit日志文件的rootnode增加一个name属性,这样就可以在xsl中根据name来区分不同的Junit测试集。
Linux下可以用shell中的sed命令来修改
Windows下使用BATCOMMAND,下面附上BAT的实现代码:
@echooff
setjunit_log_file=%1
shift
settestsuites_name=%1
shift
echo[echo]modifyJunitLogfiletocatalogJunitTestsetinmail
typenul>junit.xml
for/f"tokens=*delims="%%ain('type%junit_log_file%')doif"%%a"EQU""(
echo^>>junit.xml
)else(
echo%%a>>junit.xml
)
)
ifexistjunit.xml(
del/F%junit_log_file%
movejunit.xml%junit_log_file%
)
相应的生成测试汇总信息的xslfile也需要更改:
File:summary-test.xsl
UnitTestResults:Summary
0">TestSummaryTypeTestsFailuresErrorsSuccessrateTime0">0">0">ErrorPassWscript0Note:failuresareanticipatedandcheckedforwithassertionswhileerrorsareunanticipated.NameTestsErrorsFailuresTime(s)TimeStampHost0">Error0">FailurePassJunitTest最后邮件的内容如上所示。TestSummary中的链接指向CC的TestResults页面http://10.239.47.233:8080/cruisecontrol/buildresults/splitpoint-win32?tab=testResults);
因为Wscript不是Junit测试,所以我们需要修改CC的xsl/testdetails.xsl文件以显示Wscript测试结果。
当然我们有时并不想看所有测试的结果明细,如我只想看Wscript测试中的没有通过的testcaseWscript001,所以我写了一个JSP页面来对显示单个的testcase信息,XML源树本来想用CC的日志文件,但发现CC代码中取当前日志文件的文件名是protect方法,不能直接拿来用。于是想到使用Wscript本身的日志文件,在Testtask结束后将Wscript本身的日志文件移到logDir目录下,然后在JSP页面中load这个XML源树,即可检出所需的testcase日志信息,下附这个JSP的页面代码,这里面的难点在于如何从javascript传参到xsl(传参方法IE和Firefox不一样)。
File:mail-link.jsp">">">">functionXMLDocLoad(fname){varxmlDoc;if(window.ActiveXObject){//codeforIE//xmlDoc=newActiveXObject("Microsoft.XMLDOM");xmlDoc=newActiveXObject("MSXML2.FreeThreadedDomDocument");xmlDoc.async=false;xmlDoc.load(fname);return(xmlDoc);}elseif(document.implementation&&document.implementation.createDocument){//codeforMozilla,Firefox,Opera,etc.xmlDoc=document.implementation.createDocument("","",null);xmlDoc.async=false;xmlDoc.load(fname);return(xmlDoc);}else{alert('Yourbrowsercannothandlethisscript');}}functionShowPopularTags(){xml=XMLDocLoad("http://"+document.getElementById("servername").getAttribute("name")+":8080/cruisecontrol/logs/"+document.getElementById("project").getAttribute("name")+"/"+document.getElementById("wscript_log").getAttribute("name"));xsl=XMLDocLoad("xsl/mail-link.xsl");if(window.ActiveXObject){//codeforIEdon'tpassparametertoXSLfile//ex=xml.transformNode(xsl);//document.getElementById("popularTags").innerHTML=ex;varxslt=newActiveXObject("MSXML2.XSLTemplate.3.0");//alert(xsl.documentElement.xml);xslt.stylesheet=xsl;xsltProcessor=xslt.createProcessor();xsltProcessor.input=xml;xsltProcessor.addParameter("test_id",document.getElementById("popularTags").getAttribute("name"));xsltProcessor.transform();document.getElementById("popularTags").innerHTML=xsltProcessor.output;}elseif(document.implementation&&document.implementation.createDocument){//codeforMozilla,Firefox,Opera,etc.xsltProcessor=newXSLTProcessor();xsltProcessor.importStylesheet(xsl);xsltProcessor.setParameter(null,"test_id",document.getElementById("popularTags").getAttribute("name"));resultDocument=xsltProcessor.transformToFragment(xml,document);document.getElementById("popularTags").innerHTML="";document.getElementById("popularTags").appendChild(resultDocument);//varihtml=document.getElementById("popularTags").innerHTML;//document.getElementById("popularTags").innerHTML=ihtml;}}ShowPopularTags();