CruiseControl 小结

 

持续集成(Continuous Integration)可能对不熟悉自动化测试的部分人来说是一个新鲜词,然而它在软件开发,特别是大型的开发任务过程中,正在发挥越来越大的作用。

软件开发为了保证代码的稳定和可用,测试是必不可少的,没有哪个公司和个人敢说自己的代码100%没有BUG。在软件测试这一块,很多企业是招专门的测试工程师进行人工测试。人工测试有自己的特有的优点,但自动化测试也有自己的好的一面。

1)节约测试的人力成本

2)测试点全面,可能人有时候会忘记要对哪些点做测试,但机器不会忘记。

3)如果代码有BUG,它可以即时提供精确的日志信息和错误报告邮件发给开发者,实现错误的即时,精准定位。

4)有的测试可能人工没法完成,如对网站进行高并发访问的压力测试。

 

 

CruiseControl :简称 CC ,持续集成工具,主要提供了基于版本管理工具 ( CVSVSSSVN) 感知变化或每天定时的持续集成,并提供持续集成报告、 Email Jabber 等等方式通知相关负责人,其要求是需要进行日构建的项目已编写好全自动的项目编译脚本 ( 可基于 Maven Ant)

 

我这段时间一直在做CC的搭建工作,在不同的平台下(windows 32, windows 64, linux32, linux64 ),现在做一个小结。

 

第一步:安装CC

我现在使用的CC版本是2.8.3,可能在这之前你需要安装jdk, svn client, ant.

第二步:配置CC

启动CC的入口程序windows下是cruisecontrol.batlinux下是cruisecontrol.sh

CC 启动的时候会将配置文件以参数的方式传递给它,也可以使用默认的配置文件文件名config.xml,就像ant 命令的默认配置文件是执行命令的目录下的build.xml一样。

 

CC config.xml Sample:

<?xml version="1.0" encoding="utf-8"?>

<cruisecontrol>

      

    <property name="ant.home" value="C:/ant" />

    <property name="CCDIR"                     value="C:/nightly/cc-2.8.3" />

    <property name="CC.root"          value="C:/nightly/QAFrame/cruiseNightly" />

    <property name="CRUISE_WORKSPACE" value="${CC.root}/splitpoint-win32" />

    <property name="CC.configs"       value="${CRUISE_WORKSPACE}/configs" />

 

    <system>

        <configuration>

            <threads count="2" />

        </configuration>

    </system>

      

    <project  name="splitpoint-win32" forceOnly="false" requiremodification="false"          buildafterfailed="false">

        <property name="WORKSPACE" value="${CC.root}" />

        <property name="MAIL_FROM" value="win32 Cruise Build - Federal Test:" />

 

        <listeners>

        <currentbuildstatuslistener                         file="${CRUISE_WORKSPACE}/logs/${project.name}/status.txt" />

        <lockfilelistener lockfile="${CRUISE_WORKSPACE}/logs/splitpoint-win32.lock"  projectname="${project.name}" />

        </listeners>

 

        <modificationset quietperiod="30">

                     <svn localWorkingCopy="${WORKSPACE}" />                 

        </modificationset>

 

        <schedule interval="20">

            <!-- 常用的builder: exec, ant    -->

            <exec time="0912"

                   command="${CRUISE_WORKSPACE}/build.bat"

                            workingdir="${WORKSPACE}"  

                errorstr="run build.bat error"

                            />

        </schedule>

 

 

      <log dir="${CRUISE_WORKSPACE}/logs/${project.name}"><!-- CC 的日志目录-->

        <!-- 要集成到CC日志中的不同工程的日志目录,这些工程的日志文件是xml

            格式的,CC本身实现了对 Junit 的支持,包括Junit测试的日志文件生成和

            Web console http://localhost:8080/cruisecontrol/ 的测试结果显示;如果你                 CC中运行Junit的测试,可以使用CC自带的Junit日志文件,否则就需要自己                    写日志文件和xsl来解析

         -->

<merge dir="${WORKSPACE}/UnitTestApp/report" />

        <merge dir="${WORKSPACE}/WSScript/report" />

<merge dir="${WORKSPACE}/Webide/report" />

      </log>

      <publishers>

            <htmlemail mailhost="mailhost.pb.intel.com"

                returnaddress="SplitPoint-QA@intel.com"

                            returnname="Win32 Federal Test ( Nightly Install )"

                            subjectprefix="Federal Test (Checkin Build) :"

                skipusers="false"

                spamwhilebroken="true" <!-- send mail if CC build failed -->                                    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}">               

                            <parameter name="noCCtableWorkaround" value="yes" />

                <always address="yousuf007@163.com" />

                <failure address="yousuf007@163.com" reportWhenFixed="true" />

                     </htmlemail>

        </publishers>

    </project>

</cruisecontrol>

 

当不同的项目均需要Junit测试时,可以把它们配置在同一个build.xml 中,但它们的程序依赖,目录结构,业务功能可能不一样,而且testcase数据可能很多,所以有必要将它们的Junit Test task 放在各自的ant task 里面( 即在build.xml 配置batchtest )

 

但由于生成Junit 的日志文件(.xml 格式)是CC的内置支持功能,在没有找到CC的这部分代码的情况下,想到了另外一个解决方案。对CC生成的Junit 日志文件进行修改,给Junit 日志文件的root node <testsuites> 增加一个name属性,这样就可以在xsl 中根据name 来区分不同的Junit 测试集

Linux 下可以用 shell 中的 sed 命令来修改

Windows下使用BAT COMMAND,下面附上BAT的实现代码:

@echo off

set junit_log_file=%1

shift

set testsuites_name=%1

shift

echo [echo] modify Junit Log file to catalog Junit Test set  in mail

type nul > junit.xml

for /f "tokens=* delims= " %%a in ('type %junit_log_file%') do if "%%a" EQU "<testsuites>" (

    echo ^<testsuites name="%testsuites_name%"^> >> junit.xml

  ) else (

    echo %%a >> junit.xml

  )

)

if exist junit.xml (

  del /F %junit_log_file%

  move junit.xml %junit_log_file%

)

 

相应的生成测试汇总信息的xsl file也需要更改:

File : summary-test.xsl

<xsl:template match="/">

  <xsl:apply-templates select="/cruisecontrol" mode="summary" />

</xsl:template>

<xsl:template match="/cruisecontrol" mode="summary">

    <html>

        <head>

            <title>Unit Test Results: Summary</title>

        </head>

        <body>

        <xsl:variable name="test_report_url" select="/cruisecontrol/host/TestResultUrl"/>

 

        <xsl:variable name="wscript_test_flag" select="count(/cruisecontrol/WscriptTest)" />

        <xsl:variable name="junit_test_flag" select="count(/cruisecontrol/testsuites)" />

        <xsl:variable name="test_flag" select="( $wscript_test_flag + $junit_test_flag )"/>    

 

        <xsl:if test="$test_flag &gt; 0">    

  

        <h2>Test Summary</h2>

          

        <!--

           get test result for wscript test

        -->

 

        <xsl:variable name="fail" select="/cruisecontrol/WscriptTest/fail/text()"/>

        <xsl:variable name="total" select="/cruisecontrol/WscriptTest/total"/>

        <xsl:variable name="successRate2" select="($total - $fail) div $total"/>

     

   

        <table class="detail" border="0" cellpadding="5" cellspacing="2" width="95%">

 

        <tr valign="top" class="junit-test-info">

            <th>Type</th>

            <th>Tests</th>

            <th>Failures</th>

            <th>Errors</th>

            <th>Success rate</th>

            <th>Time</th>

        </tr>

          <!--

           display Junit Test summary

          -->

          <xsl:if test="$junit_test_flag &gt; 0">

            <xsl:call-template  name="junit_testsuites">

              <xsl:with-param name="test_report_url" select="$test_report_url"/>

            </xsl:call-template>

          </xsl:if>

 

          <xsl:if test="$wscript_test_flag &gt; 0">

          <tr valign="top">

            <xsl:attribute name="class">

                <xsl:choose>

                    <xsl:when test="$fail &gt; 0">Error</xsl:when>

                    <xsl:otherwise>Pass</xsl:otherwise>

                </xsl:choose>

            </xsl:attribute>

             <td class="junit-test-info" style="color:black">Wscript</td>

             <td>

                <a title="Display all tests">

                   <xsl:attribute name="href">

                        <xsl:value-of select="$test_report_url"/>

                   </xsl:attribute>

                   <xsl:value-of select="$total"/>

                </a>

             </td>

 

             <td><a title="Display all tests">

                <xsl:attribute name="href">

                        <xsl:value-of select="$test_report_url"/>

                   </xsl:attribute>

                <xsl:value-of select="$fail"/></a></td>

            

             <td>0</td>

 

             <td>

                <xsl:call-template name="display-percent">

                    <xsl:with-param name="value" select="$successRate2"/>

                </xsl:call-template>

             </td>

             <td>

                <xsl:value-of select="/cruisecontrol/WscriptTest/costtime" />

             </td>

          </tr>

          </xsl:if>

        </table>

        <table border="0" width="95%">

        <tr>

        <td style="text-align: justify;">

        Note: <em>failures</em> are anticipated and checked for with assertions while <em>errors</em> are unanticipated.

        </td>

        </tr>

        </table>

 

        </xsl:if>

 

       </body></html>

</xsl:template>

 

<xsl:template name="display-percent">

    <xsl:param name="value"/>

    <xsl:value-of select="format-number($value,'0.00%')"/>

</xsl:template>

 

 

<xsl:template name="display-time">

    <xsl:param name="value"/>

    <xsl:value-of select="format-number($value,'0.000')"/>

</xsl:template>

 

<!-- class header -->

<xsl:template name="testsuite.test.header">

    <tr valign="top" class="junit-test-info">

        <th width="80%">Name</th>

        <th>Tests</th>

        <th>Errors</th>

        <th>Failures</th>

        <th nowrap="nowrap">Time(s)</th>

        <th nowrap="nowrap">Time Stamp</th>

        <th>Host</th>

    </tr>

</xsl:template>

 

  <!--

   generate summary junit test such as webide, splat.war

   -->

  <xsl:template match="/cruisecontrol" mode="junit">

    <xsl:param name="test_report_url" />   

    <xsl:for-each select="testsuites">     

      <!--

           get test result for junit test

       -->

    <xsl:variable name="testCount" select="sum(testsuite/@tests)"/>

    <xsl:variable name="errorCount" select="sum(testsuite/@errors)"/>

    <xsl:variable name="failureCount" select="sum(testsuite/@failures)"/>

    <xsl:variable name="timeCount" select="sum(testsuite/@time)"/>

    <xsl:variable name="successRate1" select="($testCount - $failureCount - $errorCount) div $testCount"/>

 

    <tr valign="top">

      <xsl:attribute name="class">

        <xsl:choose>

          <xsl:when test="$errorCount &gt; 0">Error</xsl:when>

          <xsl:when test="$failureCount &gt; 0">Failure</xsl:when>

          <xsl:otherwise>Pass</xsl:otherwise>

        </xsl:choose>

      </xsl:attribute>

      <td class="junit-test-info" style="color:black">

        <xsl:choose>

          <xsl:when test="./@name">

            <xsl:value-of select="./@name"/>

          </xsl:when>

          <xsl:otherwise>Junit Test</xsl:otherwise>

        </xsl:choose>

      </td>

      <td>

        <a title="Display all tests">

          <xsl:attribute name="href">

            <xsl:value-of select="$test_report_url"/>

          </xsl:attribute>

          <xsl:value-of select="$testCount"/>

        </a>

      </td>

 

      <td>

        <a title="Display all tests">

          <xsl:attribute name="href">

            <xsl:value-of select="$test_report_url"/>

          </xsl:attribute>

          <xsl:value-of select="$failureCount"/>

        </a>

      </td>

 

      <td>

        <a title="Display all tests">

          <xsl:attribute name="href">

            <xsl:value-of select="$test_report_url"/>

          </xsl:attribute>

          <xsl:value-of select="$errorCount"/>

        </a>

      </td>

 

      <td>

        <xsl:call-template name="display-percent">

          <xsl:with-param name="value" select="$successRate1"/>

        </xsl:call-template>

      </td>

      <td>

        <xsl:call-template name="display-time">

          <xsl:with-param name="value" select="$timeCount"/>

        </xsl:call-template>

      </td>

    </tr>

    </xsl:for-each>

  </xsl:template>

 

  <xsl:template name="junit_testsuites">

    <xsl:param name="test_report_url"/>

    <xsl:apply-templates select="/cruisecontrol" mode="junit">

      <xsl:sort select="@name"/>

      <xsl:with-param name="test_report_url" select="$test_report_url"/>

    </xsl:apply-templates>

  </xsl:template>

 

 

 

最后邮件的内容如上所示。Test Summary 中的链接指向CCTest Results页面http://10.239.47.233:8080/cruisecontrol/buildresults/splitpoint-win32?tab=testResults);

因为Wscript 不是Junit 测试,所以我们需要修改CCxsl/testdetails.xsl 文件以显示Wscript测试结果。

 

当然我们有时并不想看所有测试的结果明细,如我只想看Wscript 测试中的没有通过的testcase Wscript001, 所以我写了一个 JSP 页面来对显示单个的testcase 信息,XML源树本来想用CC的日志文件,但发现CC代码中取当前日志文件的文件名是protect方法,不能直接拿来用。于是想到使用Wscript本身的日志文件,在 Test task 结束后将Wscript本身的日志文件移到 logDir 目录下,然后在 JSP 页面中 load 这个XML源树,即可检出所需的testcase日志信息,下附这个JSP的页面代码,这里面的难点在于如何从 javascript 传参到 xsl (传参方法IEFirefox不一样)。

File : mail-link.jsp

<html>

<body>

<%

  String wscript_logfile= request.getParameter("log");

  String error_id = request.getParameter("error_id");

  String project = request.getParameter("project");

  String servername = request.getServerName();

%>

 

<div id="popularTags" name="<%=error_id%>"></div>

<div id="wscript_log" name="<%=wscript_logfile%>"></div>

<div id="project" name="<%=project%>"></div>

<div id="servername" name="<%=servername%>"></div>

 

<script language="javascript" type="text/javascript">

    function XMLDocLoad(fname)

    {

    var xmlDoc;

 

    if (window.ActiveXObject){

        // code for IE

        //xmlDoc=new ActiveXObject("Microsoft.XMLDOM");

        xmlDoc=new ActiveXObject("MSXML2.FreeThreadedDomDocument");       

        xmlDoc.async=false;

        xmlDoc.load(fname);

 

        return(xmlDoc);

    }

    else if(document.implementation && document.implementation.createDocument){

        // code for Mozilla, Firefox, Opera, etc.

        xmlDoc=document.implementation.createDocument("","",null);

 

        xmlDoc.async=false;

        xmlDoc.load(fname);

 

        return(xmlDoc);

 

    }

    else{

        alert('Your browser cannot handle this script');

    }

    }

 

    function ShowPopularTags()

    {

                

           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){

                  // code for IE  don't pass parameter to XSL file             

                  //ex=xml.transformNode(xsl);

                  //document.getElementById("popularTags").innerHTML=ex;

                 

                  var xslt = new ActiveXObject("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;             

           }

           else if (document.implementation && document.implementation.createDocument){

                  // code for Mozilla, Firefox, Opera, etc.

                xsltProcessor=new XSLTProcessor();

                         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);

 

                  //var ihtml = document.getElementById("popularTags").innerHTML;

                  //document.getElementById("popularTags").innerHTML = ihtml;

            }

    }

 

    ShowPopularTags();

</script>   

 

</body>

</html>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值