CruiseControl.Net持续集成实战指南(包含如何配置c++项目)
 
2009-04-08 作者:李鑫 来源:李鑫的blog
 

我需要搭建一个C++项目的持续集成的环境 (windows的程序),所以这几天学习了一下CruiseControl.Net (以下简称CCNet),把整个过程跟大家分享一下。

如果你没有用过CCNet,跟着我实战一把,相信会领你入门的。

本文准备分三篇:

一、工具和环境的简要介绍

二、CCNet的配置(.Net项目)

三、CCNet中C++项目的配置

废话不多说了,实战开始!

工具准备:

首先说说我的实战环境

操作系统:Windows XP 专业版 其中 IIS 5.1

开发工具:Visual Studio.net 2003  Visual Studio 2005(说明一下,我的C++项目是03环境下的,05不是必需的,但是本文中我建立的C#项目是vs05的,03的效果应该是一样的,大家应该明白,实际上的问题在于.net framework的版本,因为本文中用到的开源项目有些是基于.net framework2.0的,1.1版本的我没有实际用过,不敢乱说)

dotNet Framework版本: 装vs2005自带的2.0的。

Visual SourceSafe 2005 :英文版的,源代码版本管理工具,这个vss也自带.net framework 2.0,我没有用过其他版本的vss,但是我认为对实战不会有影响。

需要的开源项目:

Cruise Control.Net 1.3

CruiseControl.NET-CCTray 1.3

NUnit-2.4.1-net-2.0

我在E盘建立了一个咱们试验的目录起个名字NetCruise。

安装Cruise Control.Net 1.3 到E:\NetCruise\CruiseControl.NET

安装 CruiseControl.NET-CCTray 1.3到E:\NetCruise\CCTray

安装 NUnit-2.4.1-net-2.0 到默认的位置了

目前的目录结构是这样的:

E:\NetCruise

CCTray

CruiseControl.NET

然后使用VSS建立一个源代码的数据库,步骤如下:

File - > New Database

在F:\MyVSS目录下建立(这个位置无所谓,只要你能记住就行),如下图:

一直下一步到结束。

第二部分

如果你对NUnit比较熟悉,可以直接进入第三部分

下面我们将建立一个简单的C# Library项目,并添加NUnit的测试。

加入代码

using System;
using System.Collections.Generic;
using System.Text;

namespace SimpleLib
{
    
public class Calculater
    
{
        
public static int add(int x, int y)
        
{
            
return x + y;
        }


        
public static int mul(int x, int y)
        
{
            
return x * y;
        }

    }

}

然后为该项目添加测试,步骤如下:

 

 添加测试类,先新建一个类,代码如下:

using System;
using System.Collections.Generic;
using System.Text;

namespace SimpleLib
{
    
using NUnit.Framework;

    [TestFixture]
    
public class CalculaterTest
    
{
        
private Calculater calculater;

        [SetUp]
        
protected void SetUp()
        
{
            calculater = 
new Calculater();
        }


        [Test]
        
public void TestAdd()
        
{
            
int i5 = 5;
            Assert.AreEqual(i5, Calculater.add(1, 4));
            Assert.AreEqual(i5, Calculater.add(2, 3));
        }


        [Test]
        
public void TestMul()
        
{
            
int i15 = 15;
            Assert.AreEqual(i15, Calculater.mul(3, 5));
            Assert.AreEqual(i15, Calculater.mul(5, 3));
        }


        [Test]
        
public void TestAddFailed()
        
{
            Assert.AreEqual(7, Calculater.mul(3, 2));
        }


        [Test]
        
public void TestAddAndMul()
        
{
            
int i15 = 15;
            Assert.AreEqual(i15, Calculater.mul(Calculater.add(2, 3), 3));
        }

    }
其中TestAddFailed方法是故意让他测试失败的。

 编译后,可以用NUnit查看一下结果,方法是启动NUnit,然后File->Open Project然后选择编译生成的SimpleLib.dll文件,选择Run就可以看到结果了。

这里说一下NUnit的颜色,红色表示失败,绿色表示通过,黄色表示测试为运行。

下面就把该项目传到vss上去,这个我现在的机器上装的是vs05英文版的,只能用英文说明如何选择了。

File->Source Control->Add solution to Source Control..

按默认的名称确定就可以了,如下图:

VSS的使用省略了不少,你应该为自己建立一个User,设置一个密码,每一个User就相当一个程序员嘛~

将除了VSS的所有东西都关掉吧!

在E:\NetCruise下新建一个project文件夹 

哦了,所有的东西准备差不多了,下一篇就介绍CCNet的配置。

上一篇介绍完咱们的实战环境,下面主要介绍如何配置CCNet好让整个持续集成框架转起来。

 这个配置文件是偶读了半天CCNet文档弄出来的,其实介绍CCNet如何配置的中文文章也不少,我阅读的时候感觉不太明白其中的每种路径干什么用的,所以我就着重讲一讲这些。

 配置清单如下:

<cruisecontrol>
    
<!-- This is your CruiseControl.NET Server Configuration file. Add your projects below! -->
  
<project name="SimpleLib" >
    
<workingDirectory>E:\NetCruise\project</workingDirectory>
    
<artifactDirectory>E:NetCruise\artifactDirectory</artifactDirectory>
    
<category>Library Category</category>
    
<webURL>http://localhost/ccnet/server/local/project/SimpleLib/ViewProjectReport.aspx</webURL>
    
<modificationDelaySeconds>2</modificationDelaySeconds>
    
<triggers>
      
<intervalTrigger seconds="60"/>
    
</triggers>
    
<!--state type="yourStateManagerType" ..=""/-->
    
<sourcecontrol type="vss" autoGetSource="true" applyLabel="true">
      
<executable>C:Program Files\Microsoft Visual SourceSafe\ss.exe</executable>
      
<project>$/SimpleLib.root</project>
      
<username>ccnet</username>
      
<password>123456</password>
      
<ssdir>F:\MyVSS</ssdir>
      
<workingDirectory>E:\NetCruise\project</workingDirectory>
    
</sourcecontrol>
    
<!--labeller type="dateLabeller"/-->
    
<!--prebuild>
            <yourFirstPrebuildTask ..=""/>
            <yourOtherPrebuildTask ..=""/>
        </prebuild-->

    
<tasks>
      
<devenv>
        
<solutionfile>E:NetCruise\project\SimpleLib\SimpleLib.sln</solutionfile>
        
<configuration>Debug</configuration>
        
<buildtype>Build</buildtype>
        
<executable>C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.com</executable>
      
</devenv>
      
<nunit path="C:\Program Files\NUnit 2.4\bin\nunit-console.exe">
        
<assemblies>
          
<assembly>E:\NetCruise\project\SimpleLib\SimpleLib\bin\Debug\SimpleLib.dll</assembly>
        
</assemblies>
      
</nunit>
    
</tasks>
    
<publishers>
      
<xmllogger />
    
</publishers>
    
<externalLinks>
      
<externalLink name="google" url="http://somewhere/" />
      
<externalLink name="My Other Link" url="http://somewhere.else/" />
    
</externalLinks>
  
</project>
</cruisecontrol>

 所有配置的路径可以参考第一篇文章来明确其含义。

 project name随便填写,还是以你的项目名为准比较好。

<workingDirectory>E:\NetCruise\project</workingDirectory>

这个指定了工作目录,那么什么是工作目录,为什么要指定呢?

一般来说有两种目的:

首先是很多其他的配置项,尤其是那种需要填写路径的,当我们用相对路径的时候,就是以工作目录作为标准的。

其次是运行程序的目录,这个有什么用呢?举个例子,比如我用C++写了段程序,程序中用如下方法写了个文件:

fstream fs("Hello.txt");//之后省略

那么,此文件的最后输出的路径就是在运行程序的目录,你可以为该exe建立一个快捷方式,然后运行一下,就会发现此文件输出到该快捷方式所在的目录下了。

<artifactDirectory>E:\NetCruise\artifactDirectory</artifactDirectory>

这个路径输出CCNet的build日志,所以你也可以指定其他路径,虽说是日志,咱们可以打开看一下这些xml的内容,最终CCNet发布build结果的网站中的数据就是根据这些xml文件配合xsl生成的。

 <category>Library Category</category>

这个元素可有可无,内容也随便起,看文档说是为了grouping projects,可以在CCTray中或者Dashboard(CCNet发布结果的网站)中显示,实际上我用没看出来什么……

<webURL>http://localhost/ccnet/server/local/project/SimpleLib/ViewProjectReport.aspx</webURL>

这个URL给CCTray和email用的,你添上你项目在Dashboard中的路径就可以了,刚开始不知道没关系,可以先不用这个元素,之后访问http://localhost/ccnet 去找到连接在加上就ok。

<modificationDelaySeconds>2</modificationDelaySeconds>

这个时间是控制代码last check in和开始build的时间,文档上举了个例子,比如说这个值设为10,代码7秒前check进来的,就sleep3秒后再build。文档上还说了,这个元素不用也可以,这是因为某些CVS不支持什么什么什么而存在的,默认值为0。(VSS做代码管理就可以不用设置这个,当然设置了也没什么毛病)

    <triggers>
      <intervalTrigger seconds="60"/>

   </triggers>

这个元素是触发器,这里简单设置了一个,60秒检测一下版本服务器,看看有没有变化,如果没有更新的版本,那么就等待60后再检查,如果有最新版本那么就build了。如果你想实现每日构件,或者设置一些特殊的东西,比如周六周日不进行build,可以参考一下CCNet的文档,有关triggers的部分,还是很好理解的,还有例子。

    <sourcecontrol type="vss" autoGetSource="true" applyLabel="true">
      <executable>C:\Program Files\Microsoft Visual SourceSafe\ss.exe</executable>
      <project>$/SimpleLib.root</project>
      <username>ccnet</username>
      <password>123456</password>
      <ssdir>F:\MyVSS</ssdir>
      <workingDirectory>E:\NetCruise\project</workingDirectory>
    </sourcecontrol>

这个东西我相信大家能理解,就是配置源代码管理的部分,里面的路径参考第一篇环境介绍很容易理解。

其中有一点需要说明,一定要把这个workingDirectory和上面的工作目录设置为相同的,这个工作目录是CCNet从版本控制中获取项目放到的目的地,而上面的工作目录是build的目录,假如放到不同的目录中,那么你可以想象,每次都build同一个版本,而你最新的版本只不过每次都get到一个目录下,并不做任何事情。

    <tasks>
      <devenv>
        <solutionfile>E:\NetCruise\project\SimpleLib\SimpleLib.sln</solutionfile>
        <configuration>Debug</configuration>
        <buildtype>Build</buildtype>
        <executable>C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.com</executable>
      </devenv>
      <nunit path="C:\Program Files\NUnit 2.4\bin\nunit-console.exe">
        <assemblies>
          <assembly>E:\NetCruise\project\SimpleLib\SimpleLib\bin\Debug\SimpleLib.dll</assembly>
        </assemblies>
      </nunit>
    </tasks>

这一块分两个部分:编译项目,运行自动化测试。

编译项目我采用了一个比较简单的方式,没用Nant什么的,devenv是VS自带的一个工具,咱们所有的IDE环境就是调用它来编译程序的。(当然你要是有vs2005的话也可以用msbuild来编译,我采用这个的目的是为了编译vc程序,因为C++的项目通常比较复杂,我不太懂怎么用一些其他的工具来编译,我发现这个方法很不错,vs03 05都可以用,还不用写新的东西来编译项目)。

nunit元素一目了然了,我保持沉默。

    <publishers>
      <xmllogger />
    </publishers>
    <externalLinks>
      <externalLink name="google" url="http://somewhere/" />
      <externalLink name="My Other Link" url="http://somewhere.else/" />
    </externalLinks>

publishers元素中间放着如何发布整个build信息的方法,CCNet中叫Task,CCNet比较好的方式就是每个程序员电脑上都运行CCTray,浏览结果的时候看Dashboard发布的build信息。

<xmllogger/>就是输出上面artifactDirectory元素所指定路径中的log信息。

externalLinks就无所谓了,可以随便写,登陆Dashboard就能看到这些链接。

好了,将这些内容放到cc.config中,保存。

然后运行CCNet(有两种方式,命令行,或者windows服务)。这里用命令行方式(桌面上的那个就行)。

E:\NetCruise\CruiseControl.NET\server\ccnet.log 存储着运行时候的日志信息,如果有错误的话可以打开这个日志看一看,按照错误提示修改一下。

如果你成功了,那么非常恭喜你,心情一定很不错。

启动CCTray吧,CCTray的使用方法我这里不说了,比较简单的,如果使用不明白的话可以查一下相关的blog,写得很详细,图文并茂。

访问http://localhost/ccnet 看看吧!

然后可以从VSS上Get这个项目到另一个目录下,然后可以改变一下代码,或者测试用例,让他们都通过,再Check in回去(中文版的vs忘了check in怎么翻译的,好像挺离谱)。等一会,如果你的配置都正确的话他会提取最新的版本然后重新build,发布测试结果!

好了,多做做试验,祝你成功!

下一篇将着重介绍VC项目如何利用CCNet进行持续集成~

首先说这篇主要参考了

http://build.sharpdevelop.net/ccnet/doc/CCNET/Using%20CruiseControl.NET%20with%20CppUnit.html

C++项目单元测试采用CPPUnit,CPPUnit的使用这里不详细讲了,有很多很不错的资料了。

cppunit中设置输出xml文件名为Result.xml

服务器配置xml如下:

  <project name="CppCal" queuePriority="1" >

    <workingDirectory>E:\NetCruise\project</workingDirectory>

    <artifactDirectory>E:\NetCruise\project\CppCal\buildinfo</artifactDirectory>

    <category>Cpp Category</category>

    <webURL>http://localhost/ccnet/server/local/project/CppCal/ViewProjectReport.aspx</webURL>

    <modificationDelaySeconds>2</modificationDelaySeconds>

    <triggers>

      <intervalTrigger seconds="60"/>

    </triggers>

    <!--state type="yourStateManagerType" ..=""/-->

    <sourcecontrol type="vss" autoGetSource="true" applyLabel="true">

      <executable>C:\Program Files\Microsoft Visual SourceSafe\ss.exe</executable>

      <project>$/CppCal.root</project>

      <username>ccnetcpp</username>

      <password>123456</password>

      <ssdir>F:\MyVSS</ssdir>

      <workingDirectory>E:\NetCruise\project</workingDirectory>

    </sourcecontrol>

    <!--labeller type="dateLabeller"/-->

    <!--prebuild>

              <yourFirstPrebuildTask ..=""/>

              <yourOtherPrebuildTask ..=""/>

         </prebuild-->

    <tasks>

      <devenv>

        <solutionfile>E:\NetCruise\project\CppCal\CppCal.sln</solutionfile>

        <configuration>Debug</configuration>

        <buildtype>Build</buildtype>

        <executable>C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.com</executable>

      </devenv>

      <nunit>

        <path>E:\NetCruise\project\CppCal\outPut\ProjectTest.exe</path>

        <assemblies>

          <assembly>*noassembly*</assembly>

        </assemblies>

        <outputfile>empty.xml</outputfile>

      </nunit>

    </tasks>

    <publishers>

      <merge>

        <files>

          <file>Result.xml</file>

        </files>

      </merge>

      <xmllogger />

    </publishers>

    <externalLinks>

      <externalLink name="google" url="http://somewhere/" />

      <externalLink name="My Other Link" url="http://somewhere.else/" />

    </externalLinks>

  </project>

需要修改一个xls文件

下载地址

http://build.sharpdevelop.net/ccnet/doc/786491/unittests.xsl

需要替换文件,注意:这个连接下载下来是unittests.xml文件,需要手动改后缀名为xsl,然后替换

在本文中的位置是

E:\NetCruise\CruiseControl.NET\webdashboard\xsl\unittests.xsl

的文件。

这个文件是老外写的,用来能在CruiseControl.Net中显示CppUnit测试的结果,本来以为很厉害,但是打开以后研究了一下,发现还是比较简单的,有兴趣可以打开自己看看(配合CCNet生成的log**.xml文件)。

 另外说一下这个Task,测试项目会生成一个exe,我们CPPUnit要用控制台那种,而且最终要以

return result.wasSuccessful() ? 0 : 1;

这种方式return,如果test成功他会返回0,CCNet如果发现程序返回0,那么表示测试成功,咱们的CCTray就是绿色的,如果返回1则相反,这样VC项目就会很好的进行构建。

      <nunit>

        <path>E:\NetCruise\project\CppCal\outPut\ProjectTest.exe</path>

        <assemblies>

          <assembly>*noassembly*</assembly>

        </assemblies>

        <outputfile>empty.xml</outputfile>

      </nunit>


火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。
资源网站: UML软件工程组织