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

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

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

自动获取源代码

自动Build

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

自动部署

触发自动化(回归)测试

邮件提醒

使用CCTray进行监控

应用plugin显示集成结果

设置集成策略

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

  获取SVN或TFS工具,TFS可通过安装VisualStudio获得,SVN可通过安装TortoiseSVN来获得。

  安装和配置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[];
string trxUutPutFileName = args[];
string coverageoutPutFileName = args[]; 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="my@sina.com" mailhostPassword="******" useSSL="FALSE">
<from>my@sina.com</from>
<mailhost>smtp.sina.net</mailhost>
<users>
<user name="张三" group="developers" address="123@sina.com" />
<user name="李四" group="developers" address="456@sina.com" />
<user name="王五" group="developers" address="789@sina.com" />
</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站点后,我们的测试结果也会被格式化地显示出来。

9.设置集成策略

以每日构建为例,需要在<triggers></triggers>里配置如下结果:

<scheduleTrigger time="23:30" buildCondition="ForceBuild" name="Scheduled">
<weekDays>
<weekDay>Monday</weekDay>
<weekDay>Tuesday</weekDay>
<weekDay>Wednesday</weekDay>
<weekDay>Thursday</weekDay>
<weekDay>Friday</weekDay>
</weekDays>
</scheduleTrigger>

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

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

  1. CruiseControl.Net全面实现持续集成

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

  2. (转)使用CruiseControl+SVN+ANT实现持续集成之二

    1. 环境搭建 1.1. 下载及目录介绍 从官方站点http://cruisecontrol.sourceforge.net/download.html下载一份最新的 CC 压缩包,最新的版本号为2. ...

  3. (转)使用CruiseControl+SVN+ANT实现持续集成之三

    在上一节中我们介绍了环境搭建和配置介绍,并快速启动CC查看集成结果,在本节中我们将详细介绍CC构建操作及监视. 1. 启动CC服务器 通过执行其根目录下的cruisecontrol.bat文件来启动C ...

  4. (转)使用SVN+CruiseControl+ANT实现持续集成之一

    在前面的文章中, 介绍自己当时所在团队的处境(使用.NET开发),一个不到十个人的研发团队在保证正常开发进度同时需要并发支持四.五十个项目问题处理,经常为了程序版 本冲突.日常测试版本.发布版本提供等 ...

  5. 持续集成之戏说Check-in Dance

    尽管Thoughtworks的首席科学家Martion folwer 为“持续集成 ” 下了定义,但由于自身背景与经历的不同,每个人对其都有不同的理解.从狭义上讲,持续集成可以认为是一种基于某种或者某 ...

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

    add by zhj: 先说一下持续集成的定义,这是ThoughtWorks首席科学家Martin Fowler在<持续集成>第二版中给出的,“持续集成是一种软件开发实践.在持续集成中,团 ...

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

    刚换了工作,有需要搭建一套持续集成的平台,做一下总结. 首先是我用到的工具: 上面缺少了Microsoft Fxcop,可以用来做代码校验,不过实际情况暂时还没有用到.主要的需求目前是,使用已发布的稳 ...

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

    CruiseControl是CIserver的老者,诞生已是多年,在很多方面,CruiseControlserver已经成为持续集成实践的同义词.而如今,CruiseControl已发展成为一个家族式 ...

  9. 持续集成及部署利器:Go

    Go是一款先进的持续集成和发布管理系统,由ThoughtWorks开发.(不要和Google的编程语言Go混淆了!)其前身为CruiseControl,是ThoughtWorks在做咨询和交付交付项目 ...

随机推荐

  1. TSql 巧用Alt 键

    1,查看表的信息 在TSql 编辑器中,选中一个表,如图 点击Alt+F1,就可以查看表的属性定义 2,使用alt批量插入逗号 在Tsql中使用 in 子句,在(value_List)列表中,经常有很 ...

  2. Android实现播放视频

    转载:http://www.bdqn.cn/news/201311/12100.shtml 使用VideoView播放视频 VideoView,用于播放一段视频媒体,它继承了SurfaceView,位 ...

  3. .NET平台开源项目速览(4).NET文档生成工具ADB及使用

    很久以前就使用ADB这个工具来生成项目的帮助文档.功能强大,在学习一些开源项目的过程中,官方没有提供CHM帮助文档,所以为了快速的了解项目结构和注释.就生成文档来自己看,非常好用.这也是一个学习方法吧 ...

  4. Python深入06 Python的内存管理

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 语言的内存管理是语言设计的一个重要方面.它是决定语言性能的重要因素.无论是C语言的 ...

  5. SubSonic3.0.0.4.3源码包与调用Dll

    版本修改历史 3.0.0.4.3版修复了下面问题: 修正多表关联查询时,使用左关联和右关联出错问题修正DbDataProvider.cs类的ToEnumerable函数打开数据库链接后没有关闭的问题添 ...

  6. ASP.NET:在一般处理程序中通过 Session 保存验证码却无法显示图片?

    using System.Drawing; using System.Web; using System.Web.SessionState; /// <summary> /// Captc ...

  7. DDD 领域驱动设计-“臆想”中的实体和值对象

    其他博文: DDD 领域驱动设计-三个问题思考实体和值对象 DDD 领域驱动设计-三个问题思考实体和值对象(续) 以下内容属于博主"臆想",如有不当,请别当真. 扯淡开始: 诺兰的 ...

  8. php使用递归创建多级目录

    <?php header('Content-type:text/html;charset=utf8'); echo "Loading time:".date('Y-m-d H ...

  9. [Data Structure & Algorithm] Hash那点事儿

    哈希表(Hash Table)是一种特殊的数据结构,它最大的特点就是可以快速实现查找.插入和删除.因为它独有的特点,Hash表经常被用来解决大数据问题,也因此被广大的程序员所青睐.为了能够更加灵活地使 ...

  10. ZOJ Problem Set - 1392 The Hardest Problem Ever

    放了一个长长的暑假,可能是这辈子最后一个这么长的暑假了吧,呵呵...今天来实验室了,先找了zoj上面简单的题目练练手直接贴代码了,不解释,就是一道简单的密文转换问题: #include <std ...