使用CruiseControl.Net全面实现持续集成

持续集成想必大家很多人都听说过,甚至都实践过,最近我又一次亲历了一次持续集成,现将我的经验分享给大家。关于持续集成的理论在本文概不涉及,本文的主要目的是实战CruiseControl.Net,用它来全面实现持续集成。

在配置ccnet.config时会用到一些小工具,一并附上:小工具下载

首先,我们来看看用CC.Net能为我们做哪些事情:

自动获取源代码

自动Build

自动执行UnitTest,并生成单元测试报告

自动部署

触发自动化(回归)测试

邮件提醒

使用CCTray进行监控

应用plugin显示集成结果

在开始之前,第一件事是配置我们的持续集成环境

  安装和配置IIS,因为我们要使用Web页面查看持续集成的结果,所以需要配置IIS,安装CruiseControl.Net时会为我们创建一个名为ccnet的web应用程序。

  从http://www.cruisecontrolnet.org/这个站点上现在我们需要的工具CruiseControl.Net并将其安装。

  安装VisualStudio2013(当然也可选其它版本)。安装它的目的有两个,1. 使用了VSTest.Console.exe产生单元测试结果数据(UnitTest结果和测试覆盖率),2. 当编译不能通过时用它可以发现问题。

到此为止,集成环境已经OK,下面,我们来逐一来通过配置ccnet.config实现上述功能。

1.自动获取源代码

首先需要了解,持续集成的单位是以项目为单位,在ccnet.config文件里体现为Project,如下:

<project name="MyProject"
             description="demoproject showing a small config" queue="Q1">
  <!--内部配置-->
</project>

配置项目的源代地址,包括本地工作地址和源代码管理服务地址,对于使用TFS的源码管理器,向Project下添加如下配置:

<workingDirectory>E:\dailybuild</workingDirectory>
<artifactDirectory>E:\dailybuild</artifactDirectory>
<category>TestProject</category>
<sourcecontrol type="vsts" autoGetSource="true"  applyLabel="false">
  <server>http://tfs1.TestProject.com:8080</server>
  <domain>TestProject.com</domain>
  <project>$/TestProject projects/Analysis and Design\Concierge\Prototype</project>
  <workingDirectory>E:\dailybuild\TestProject</workingDirectory>
  <cleanCopy>true</cleanCopy>
</sourcecontrol>

对于使用svn源码管理器,可以使用以下配置:

<artifactDirectory>d:\svn\Log\MyProject</artifactDirectory>
<sourcecontrol type="svn">
  <executable>C:\Program Files\TortoiseSVN\bin\svn.exe</executable>
  <username>UserName</username>
  <password>******</password>
  <autoGetSource>true</autoGetSource>
  <trunkUrl>http://svnserver/trunk/MyProject</trunkUrl>
  <workingDirectory>d:\svn\trunk\MyProject</workingDirectory>
</sourcecontrol>

2.实现自动Build,向Project节点下增加tasks节点,如下

<tasks>
  <msbuild>
    <executable>C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe</executable>
    <buildArgs>/p:OutputPath=D:\BuildOutput</buildArgs>
    <workingDirectory>D:\svn\branch\project\</workingDirectory>
    <projectFile>mysolution.sln</projectFile>
    <targets>Build</targets>
    <timeout>9000</timeout>
  </msbuild>
</tasks>

3.自动执行UnitTest,并生成单元测试报告

如果要生成单元测试报告和单元测试覆盖率,这里需要多下写功夫去配置。首先在创建Runsettings文件,如下:

CodeCoverage.runsettings的配置内容如下:

<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <RunConfiguration>
    <!-- Path relative to solution directory -->
    <ResultsDirectory>d:\svn\log\TestResults</ResultsDirectory>

    <!-- [x86] | x64
      - You can also change it from menu Test, Test Settings, Default Processor Architecture -->
    <TargetPlatform>x86</TargetPlatform>

    <!-- Framework35 | [Framework40] | Framework45 -->
    <TargetFrameworkVersion>Framework40</TargetFrameworkVersion>
  </RunConfiguration>
  <DataCollectionRunSettings>
    <DataCollectors>
      <DataCollector friendlyName="Code Coverage" uri="datacollector://Microsoft/CodeCoverage/2.0" assemblyQualifiedName="Microsoft.VisualStudio.Coverage.DynamicCoverageDataCollector, Microsoft.VisualStudio.TraceCollector, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
        <Configuration>
          <CodeCoverage>
            <!-- Match assembly file paths: -->
            <ModulePaths>
              <Include>
                <ModulePath>.*\.dll$</ModulePath>
                <ModulePath>.*\.exe$</ModulePath>
              </Include>
              <Exclude>
                <ModulePath>.*CPPUnitTestFramework.*</ModulePath>
              </Exclude>
            </ModulePaths>

            <!-- Match fully qualified names of functions: -->
            <!-- (Use "\." to delimit namespaces in C# or Visual Basic, "::" in C++.)  -->
            <Functions>
              <Exclude>
                <Function>^Fabrikam\.UnitTest\..*</Function>
                <Function>^std::.*</Function>
                <Function>^ATL::.*</Function>
                <Function>.*::__GetTestMethodInfo.*</Function>
                <Function>^Microsoft::VisualStudio::CppCodeCoverageFramework::.*</Function>
                <Function>^Microsoft::VisualStudio::CppUnitTestFramework::.*</Function>
              </Exclude>
            </Functions>

            <!-- Match attributes on any code element: -->
            <Attributes>
              <Exclude>
                <!-- Don’t forget "Attribute" at the end of the name -->
                <Attribute>^System.Diagnostics.DebuggerHiddenAttribute$</Attribute>
                <Attribute>^System.Diagnostics.DebuggerNonUserCodeAttribute$</Attribute>
                <Attribute>^System.Runtime.CompilerServices.CompilerGeneratedAttribute$</Attribute>
                <Attribute>^System.CodeDom.Compiler.GeneratedCodeAttribute$</Attribute>
                <Attribute>^System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute$</Attribute>
              </Exclude>
            </Attributes>

            <!-- Match the path of the source files in which each method is defined: -->
            <Sources>
              <Exclude>
                <Source>.*\\atlmfc\\.*</Source>
                <Source>.*\\vctools\\.*</Source>
                <Source>.*\\public\\sdk\\.*</Source>
                <Source>.*\\microsoft sdks\\.*</Source>
                <Source>.*\\vc\\include\\.*</Source>
              </Exclude>
            </Sources>

            <!-- Match the company name property in the assembly: -->
            <CompanyNames>
              <Exclude>
                <CompanyName>.*microsoft.*</CompanyName>
              </Exclude>
            </CompanyNames>

            <!-- Match the public key token of a signed assembly: -->
            <PublicKeyTokens>
              <!-- Exclude Visual Studio extensions: -->
              <Exclude>
                <PublicKeyToken>^B77A5C561934E089$</PublicKeyToken>
                <PublicKeyToken>^B03F5F7F11D50A3A$</PublicKeyToken>
                <PublicKeyToken>^31BF3856AD364E35$</PublicKeyToken>
                <PublicKeyToken>^89845DCD8080CC91$</PublicKeyToken>
                <PublicKeyToken>^71E9BCE111E9429C$</PublicKeyToken>
                <PublicKeyToken>^8F50407C4E9E73B6$</PublicKeyToken>
                <PublicKeyToken>^E361AF139669C375$</PublicKeyToken>
              </Exclude>
            </PublicKeyTokens>

            <!-- We recommend you do not change the following values: -->
            <UseVerifiableInstrumentation>True</UseVerifiableInstrumentation>
            <AllowLowIntegrityProcesses>True</AllowLowIntegrityProcesses>
            <CollectFromChildProcesses>True</CollectFromChildProcesses>
            <CollectAspDotNet>False</CollectAspDotNet>

          </CodeCoverage>
        </Configuration>
      </DataCollector>
    </DataCollectors>
  </DataCollectionRunSettings>
</RunSettings>

里面最重要的信息室配置了单元测试结果存放路径:<ResultsDirectory>d:\svn\log\TestResults</ResultsDirectory>,以便我们后来生成测试结果。

接着来配置ccnet.config,以执行单元测试

<!--删除上次单元测试结果-->
<exec>
  <executable>D:\svn\tool\delfile.bat</executable>
  <buildArgs>D:\svn\Log\TestResultsReal\mstest-results.trx</buildArgs>
  <buildTimeoutSeconds>300</buildTimeoutSeconds>
  <successExitCodes>-1,0</successExitCodes>
</exec>
<exec>
  <executable>D:\svn\tool\delfile.bat</executable>
  <buildArgs>D:\svn\Log\TestResultsReal\mstest-coverage.xml</buildArgs>
  <buildTimeoutSeconds>300</buildTimeoutSeconds>
  <successExitCodes>-1,0</successExitCodes>
</exec>
<!--执行单元测试-->
<exec>
  <executable>C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\VSTest.Console.exe</executable>
  <baseDirectory>D:\svn\UnitTest.dll所在的文件目录</baseDirectory>
  <buildArgs>UnitTest.dll /Enablecodecoverage /Settings:D:\svn\tool\CodeCoverage.runsettings /logger:trx</buildArgs>
  <buildTimeoutSeconds>300</buildTimeoutSeconds>
</exec>
<!--生成测试覆盖率-->
<exec>
  <executable>
    <!--删除上次单元测试结果-->
    <exec>
      <executable>D:\svn\tool\delfile.bat</executable>
      <buildArgs>D:\svn\Log\TestResultsReal\mstest-results.trx</buildArgs>
      <buildTimeoutSeconds>300</buildTimeoutSeconds>
      <successExitCodes>-1,0</successExitCodes>
    </exec>
    <exec>
      <executable>D:\svn\tool\delfile.bat</executable>
      <buildArgs>D:\svn\Log\TestResultsReal\mstest-coverage.xml</buildArgs>
      <buildTimeoutSeconds>300</buildTimeoutSeconds>
      <successExitCodes>-1,0</successExitCodes>
    </exec>
    <!--执行单元测试-->
    <exec>
      <executable>C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\VSTest.Console.exe</executable>
      <baseDirectory>D:\svn\UnitTest.dll所在的文件目录</baseDirectory>
      <buildArgs>UnitTest.dll /Enablecodecoverage /Settings:D:\svn\tool\CodeCoverage.runsettings /logger:trx</buildArgs>
      <buildTimeoutSeconds>300</buildTimeoutSeconds>
    </exec>
    <!--生成测试覆盖率-->
    <exec>
      <executable>D:\svn\tool\coverage\Auto.Dealer.UnitTest.Tool.exe</executable>
      <buildArgs>D:\svn\log\TestResults\ D:\svn\log\TestResultsReal\mstest-results.trx D:\svn\log\TestResultsReal\mstest-coverage.xml</buildArgs>
      <buildTimeoutSeconds>300</buildTimeoutSeconds>
      <successExitCodes>-1,0</successExitCodes>
    </exec>

    <!--合并xml文件-->
    <merge>
      <files>
        <file>D:\svn\Log\TestResultsReal\mstest-results.trx</file>
        <!--这个文件是用于合并UnitTest result-->
      </files>
    </merge>
    <merge>
      <files>
        <file>D:\svn\Log\TestResultsReal\mstest-coverage.xml</file>
        <!--这个文件是用于合并UnitTest result-->
      </files>
    </merge>D:\svn\tool\coverage\Auto.Dealer.UnitTest.Tool.exe</executable>
  <buildArgs>D:\svn\log\TestResults\ D:\svn\log\TestResultsReal\mstest-results.trx D:\svn\log\TestResultsReal\mstest-coverage.xml</buildArgs>
  <buildTimeoutSeconds>300</buildTimeoutSeconds>
  <successExitCodes>-1,0</successExitCodes>
</exec>

<!--合并xml文件-->
<merge>
  <files>
    <file>D:\svn\Log\TestResultsReal\mstest-results.trx</file>
    <!--这个文件是用于合并UnitTest result-->
  </files>
</merge>
<merge>
  <files>
    <file>D:\svn\Log\TestResultsReal\mstest-coverage.xml</file>
    <!--这个文件是用于合并UnitTest result-->
  </files>
</merge>

这里,想必大家已经注意到有两处删除操作,因为持续集成式一个不断重复的过程,如果不删除原来的测试结果就会发生错误。另外,用到的一个工具(这个工具里的代码很简单,一并提供出来如下),用来将trx文件转化为xml文件,即单元测试覆盖率结果。最后将它们一起合并到CruiseControl的执行日志里。

生成单元测试覆盖率代码如下:

    class Program
    {
        static void Main(string[] args)
        {
            string dirName = args[0];
            string trxUutPutFileName = args[1];
            string coverageoutPutFileName = args[2];

            if (Directory.Exists(dirName))
            {
                DirectoryInfo dirc = new DirectoryInfo(dirName);
                foreach (FileInfo file in dirc.GetFiles("*.trx"))
                {
                    file.CopyTo(trxUutPutFileName, true);
                    break;
                }

                foreach (FileInfo file in dirc.GetFiles("*.coverage", SearchOption.AllDirectories))
                {
                    ConvertToXML(file.FullName, coverageoutPutFileName);
                    break;
                }

                dirc.Delete(true);
            }
            else
            {
                Console.WriteLine("没找到目录:"+dirName);
            }
        }

        public static void ConvertToXML(string coverageFile, string outputFile)
        {
            using( CoverageInfo coverageInfo = CoverageInfo.CreateFromFile(coverageFile))
            {
                using (CoverageDS ds = coverageInfo.BuildDataSet())
                {
                    ds.ExportXml(outputFile);
                }
            }
        }
    }

4.自动部署

<!--发布到站点-->
<buildpublisher>
  <sourceDir>d:\svn\_PublishedWebsites\MyWeb</sourceDir>
  <publishDir>\\IP地址\website\</publishDir>
  <useLabelSubDirectory>false</useLabelSubDirectory>
</buildpublisher>

5. 触发自动化(回归)测试

如果有自动化测试框架,则可以考虑部署完毕后自动触发执行自动化测试,由于自动化测试框架可能会有很大差异,这里就不在给出配置,总的来说,使用<exec></exec>可以很灵活地实现我们的需求。

6. 邮件提醒功能

无论持续集成执行成功,还是失败,都可以配置相应的邮件接收人员。邮件配置要放到<publishers></publishers>。这样,邮件发送的失败就不会阻塞持续集成。

<publishers>
  <email mailport="25" includeDetails="TRUE" mailhostUsername="[email protected]" mailhostPassword="******" useSSL="FALSE">
    <from>[email protected]</from>
    <mailhost>smtp.sina.net</mailhost>
    <users>
      <user name="张三" group="developers" address="[email protected]" />
      <user name="李四" group="developers" address="[email protected]" />
      <user name="王五" group="developers" address="[email protected]" />
    </users>
    <groups>
      <group name="developers">
        <notifications>
          <notificationType>Failed</notificationType>
          <notificationType>Fixed</notificationType>
        </notifications>
      </group>
      <group name="buildmaster">
        <notifications>
          <notificationType>Always</notificationType>
        </notifications>
      </group>
    </groups>
    <converters>
      <regexConverter find="$" replace="@sina.com" />
    </converters>
    <modifierNotificationTypes>
      <NotificationType>Failed</NotificationType>
      <NotificationType>Fixed</NotificationType>
    </modifierNotificationTypes>
    <subjectSettings>
      <subject buildResult="StillBroken" value="Build is still broken for {CCNetProject}" />
    </subjectSettings>
  </email>
  <statistics />
  <xmllogger />
</publishers>

7. 使用CCTray监控持续集成

打开http://CruiseControl所在机的IP/ccnet/,可以看到如下连接,下载并安装。就可以监控制定的项目了。

8.应用plugin显示集成结果

最后,做了以上所有的事情以后,在http://CruiseControl所在机的IP/ccnet/这个站点上并不能看到我们所有的持续集成结构,CruiseControl为我们提供了一些Plugins,即一些xsl文件,使用它们就可以显示我们想要的结果了。这些xsl文件的地址为:CruiseControl的安装路径\CruiseControl.NET\webdashboard\xsl。我们需要修改一下dashboard.config这个文件,我向其中添加了如下内容:

<buildPlugins>
  <buildReportBuildPlugin>
    <xslFileNames>
      <xslFile>xsl\header.xsl</xslFile>
      <xslFile>xsl\modifications.xsl</xslFile>
      <xslFile>xsl\unittests.xsl</xslFile>
      <xslFile>xsl\MsTestSummary2008.xsl</xslFile>
      <xslFile>xsl\compile-msbuild.xsl</xslFile>
      <xslFile>xsl\SimianSummary.xsl</xslFile>
      <xslFile>xsl\MsTestSummary2010.xsl</xslFile>
      <xslFile>xsl\MsTestSummary.xsl</xslFile>
      <xslFile>xsl\MsTestReport2010.xsl</xslFile>
      <xslFile>xsl\MsTestCover2010.xsl</xslFile>
    </xslFileNames>
  </buildReportBuildPlugin>
</buildPlugins>

这样,重启ccnet站点后,我们的测试结果也会被格式化地显示出来。

至此,我们的持续集成也基本上可以告一段落了。可以使用它来进行一些自动化的工作了。

时间: 2024-08-29 17:20:49

使用CruiseControl.Net全面实现持续集成的相关文章

持续集成之戏说Check-in Dance(转)

add by zhj: 先说一下持续集成的定义,这是ThoughtWorks首席科学家Martin Fowler在<持续集成>第二版中给出的,“持续集成是一种软件开发实践.在持续集成中,团队成员频繁集成他们的工作成果,一般每人每天至少集成一次,也可以多次.每次集成会经过自动构建(包括自动测试)的验证,以尽快发现集成错误.许多团队发现这种方法可以显著减少集成引起的问题,并可以加快团队合作软件开发的速度.” 这里是<持续集成>第二版的一些简单介绍:http://www.infoq.co

搭建你的持续集成环境——CruiseControl介绍

虽然起了个煞有介事的标题,但是其实只是把在工作中碰到的跟CruiseControl这个工具打交道的经历记录下来,因为听说有个技术博客找工作会加分很多(笑),嗯,让我们开始吧! 相信百度到CruiseControl的同学也已经知道持续集成(CI)是个什么玩意了,这篇文章的作者很懒,就不多废话了,贴上两个百度百科的链接. 关于持续集成 关于CruiseControl 先放上一张使用中的CruiseControl的架构图,然后就有点困了,嗯,那就再见~

持续集成:CruiseControl.NET + VisualSVN.Server

刚换了工作,有需要搭建一套持续集成的平台,做一下总结. 首先是我用到的工具: 上面缺少了Microsoft Fxcop,可以用来做代码校验,不过实际情况暂时还没有用到.主要的需求目前是,使用已发布的稳定版本代码作为新发布版本代码的基础,避免有未完成的代码存在于发布版本中,同时自动化集成发布后,上传该新发布版本代码到tags中.elevate一般情况下是不需要的,不过VisualSVN无法使用命令行登陆,可以使用它来提升执行权限,不过最终我使用了另外一个办法,这个方法需要购买VisualSVN S

搭建你的持续集成server - CruiseControl step by step(1)

CruiseControl是CIserver的老者,诞生已是多年,在很多方面,CruiseControlserver已经成为持续集成实践的同义词.而如今,CruiseControl已发展成为一个家族式系统,包含CruiseControl.java.CruiseControl.net.CruiseControl.ruby等适应不同语言环境的实现,其强大的插件和扩展能力也是诸多同类系统无法比你的.而在这里,我仅仅介绍该家族的本家CruiseControl.java,即CruiseControl.Cr

持续交付之三——持续集成

其他持续交付相关文章:<持续交付>系列文章目录 第三章 持续集成 1. 引言 持续集成的目标是让软件一直处于可工作的状态 2. 实现持续集成 2.1. 准备工作 版本控制 自动化构建 团队共识 2.2. 一个基本的持续集成系统 开发人员使用持续集成服务的简单流程 查看一下是否有构建正在运行,如果有的话,等它完事,如果它失败了,就和团队的其他人把他一起修复,然后再提交代码 一旦构建完成且测试完全通过,就从版本控制库中将该版本的代码更新到自己的开发环境上 在自己的开发机上执行构建脚本,运行测试,以

持续集成简介(转)

作者:许振坪,http://blog.csdn.net/benkaoya 1. 什么是“持续集成” 持续集成(ContinuousIntegration,简称CI)是持续地编译.测试.检查和部署源代码的过程.在许多持续集成环境中,这意味着每当源代码管理库中(比如 Subversion 或Git等)的代码发生改变时,都要执行新的构建.CI 的好处很明确:经常组装软件可以大大提高在早期发现缺陷的可能性,而缺陷在早期还不复杂,容易解决. 更详细的介绍可以参考IBM的一篇文章<敏捷开发中的持续集成>:

持续集成(Continuous Integration)

持续集成简称CI,持续集成是频繁.持续的在多个团队成员的工作中进行集成,并且给与反馈.一个典型的持续集成周期包括以下几个步骤:   1. 持续集成服务器不断从版本控制服务器上检查代码状态,看代码是否有更新.   2. 如果发现代码有最新的提交,那么就从版本控制服务器下载最新的代码.   3. 等代码完全更新以后,调用自动化编译脚本,进行代码编译.   4. 运行所有的自动化测试.   5. 进行代码分析.   6. 产生可执行的软件,能够提供给测试人员进行测试.   持续集成服务器,比如Crui

持续集成及部署利器:Go(不要和Google的编程语言Go混淆了!)

Go是一款先进的持续集成和发布管理系统,由ThoughtWorks开发.(不要和Google的编程语言Go混淆了!)其前身为CruiseControl,是ThoughtWorks在做咨询和交付交付项目时自己开发的一款开源的持续集成工具.后来随着持续集成及持续部署的火热,ThoughtWorks专门成立了一个项目组,基于Cruise开发除了Go这款工具.ThoughtWorks开源持续交付工具Go,Go的官方网站是http://www.go.cd/,其文档是http://www.thoughtwo

持续集成工具Jenkins学习总结

概述 持续集成(Continuous Integration,简称CI)是一种软件开发实践,团队开发人员每次都通过自动化的构建(编译.发布.自动化测试)来验证,从而尽早的发现集成错误.持续集成最大的优点是避免了传统模式在集成阶段的除虫会议(bug meeting),其要素包括统一的代码库.自动构建.自动测试.自动部署.频繁提交修改过的代码等. Jenkins的前身是Hudson,是基于Java开发的一种持续集成工具,是一个开源软件项目,主要用于: 持续.自动地构建/测试软件项目,如CruiseC