使用 CruiseControl.NET、NAnt、CVS 和 NUnit 进行持续集成





4.00/5 (13投票s)
配置持续集成服务器的指南。
引言
最近,我为 .NET 开发团队建立了一个构建系统。我对 持续集成 方法很感兴趣,在该方法中,当在源代码管理中检测到更改时,构建会自动发生。我的其他目标是让团队的构建过程保持简单易懂,并将任务分组,使其有意义并鼓励重用。
我的大部分信息来自阅读其他开发人员在网上记录的经验,但我找不到一本全面的“新手指南”来介绍如何设置整个系统。我的目的是提供这样一篇文章,解释我决策背后的逻辑,并可能简化其他人实现类似系统的过程。
本文假定您已经设置了必要的工具。我使用了 Visual Studio 2005、CruiseControl.NET 1.0.1、NAnt 0.85-rc3 和 NUnit 2.2.7。Tortoise CVS 1.8.26 用作 CVS 客户端,并且 CruiseControl.NET 的 Web 仪表板需要 IIS。
背景
开发者的工具集通常至少包含以下工具:
- 源代码管理存储库:将代码存储在公共位置,并允许多个开发人员共享代码库(例如,CVS、Subversion、VSS)。
- 单元测试框架:运行作为代码开发过程一部分编写的单元测试,并可以标记代码的意外更改(例如,NUnit、JUnit)。
- 自动构建工具:允许从命令行进行构建并执行相关任务(例如,Ant、NAnt、MSBuild)。
- 持续集成工具:监视代码更改并触发构建(例如,CruiseControl、Draco)。
多年来,构建工具的复杂性不断增加,并且许多工具的功能有所重叠。因此,实现决策可能无穷无尽。例如,单元测试应该直接从 CruiseControl、NAnt 还是 MSBuild 运行?如果使用电子邮件通知,应该如何连接?答案在于每个工具的优点和缺点,但实现或调查每一个都可能耗费大量时间。
流控制
为了帮助理解此系统的工作原理以及每个组件的作用,我提供了一个典型场景:
- 开发人员将代码更改/添加提交到 CVS。
- CruiseControl.NET 检测到更改。
- CruiseControl.NET 在构建计算机上更新代码。
- CruiseControl.NET 调用 NAnt 脚本。
- NAnt 脚本使用 devenv.com 构建应用程序。
- NAnt 脚本运行单元测试。最终的 CruiseControl.NET 任务支持显示单元测试信息。
- CruiseControl.NET 管理输出文件,以便在 Web 仪表板中显示。
- CruiseControl.NET 在适当的时候发送电子邮件。
持续集成工具:CruiseControl.NET
在两个最常见的开源持续集成工具中,我选择了 CruiseControl.NET。我没有花很多时间进行比较,我的决定是基于一些开发人员认为它更灵活。它最实用的功能是能够 轮询源代码管理中的更改,以及一个强大的 Web 仪表板(需要 IIS),它提供了所有构建及其详细信息的历史记录。
初始设置
繁重的工作将涉及在 ccnet.config 文件中设置一个 项目块。除此之外,您可能还想在 ccnet.exe.config 文件中打开日志记录。
自动构建工具:NAnt
我发现,与直接从 CruiseControl 运行单元测试和构建相比,在 NAnt(由 CruiseControl 调用)中运行它们更易于管理。将构建和单元测试打包到单个 NAnt 脚本中也便于脚本调试,并为开发人员提供了一个可以在需要时从命令行构建和测试的工具。由于 default.build 文件与项目的其余部分一起被签入 CVS,因此更改它将导致 CruiseControl.NET 重新构建。
NAnt 和 CruiseControl.NET 都可以运行任何可执行文件,并有专门用于运行单元测试的标签。但是,NAnt 为文件管理等辅助任务提供了更多支持,并且其流程控制更灵活。
初始设置
在项目的基目录中设置一个 default.build NAnt 文件,该文件构建项目并运行 NUnit 测试。对于测试,我推荐 Thea Burger 的模式,该模式允许来自多个程序集的单元测试全部完成,即使其中一个程序集可能失败。
<target name="test" description="runs the unit tests" >
<!-- test first Assembly. -->
<exec program="nunit-console.exe" failonerror="false"
resultproperty="testresult.Main.exe">
<arg value="RelativePath/Main.exe" />
<arg value="/xml=UnitTest-Main.xml" />
</exec>
<!-- test second Assembly. -->
<exec program="nunit-console.exe" failonerror="false"
resultproperty="testresult.SecondaryAssembly.dll">
<arg value="RelativePath/SecondaryAssembly.dll" />
<arg value="/xml=UnitTest-SecondaryAssembly.xml" />
</exec>
<!-- Check the results properties and fail if necessary -->
<fail message="Failures reported in unit tests."
unless="${int::parse(testresult.Main.exe)==0}" />
<fail message="Failures reported in unit tests."
unless="${int::parse(testresult.SecondaryAssembly.dll)==0}" />
</target>
编译器:MSBuild.exe 或 Devenv.com
这是从 NAnt 或命令行构建 .NET 解决方案或项目的两个选项。我尝试了两者,但使用了 devenv.com,因为当前版本的 MSBuild 无法构建安装程序文件!MSBuild 提供了与 Ant/NAnt 系列重叠的其他功能,并且一些开发人员更喜欢它而不是 devenv,因为它不需要在构建计算机上安装 Visual Studio。但是,安装程序的缺点是一个交易破坏者,并且在此过程中没有必要同时使用 MSBuild 和 NAnt。
值得注意的是,有些工具属于解决方案,位于后置构建事件中。混淆就是一个例子,它仅作为 Release 构建的一部分发生,并且需要在构建安装程序文件 *之前* 运行。
其他工具:CVS 和 NUnit
对于我的项目,CVS 和 NUnit 的选择是预先确定的。CruiseControl 提供类似的工具 来监视各种其他代码存储库。NUnit 很普遍,并且我的团队在多个项目上都使用过它。
更多 CruiseControl.NET 设置技巧
Merge 标签
根据您连接 CruiseControl.NET 的方式,可能需要“合并”调用应用程序的输出,以便测试结果显示在 Web 仪表板和电子邮件消息中。在调用 NAnt 中的 NUnit 时就是这种情况,如上所述。当 NAnt 调用 NUnit 时,会显式请求 XML 输出。
<exec program="nunit-console.exe" failonerror="false"
resultproperty="testresult.Main.exe">
<arg value="RelativePath/Main.exe" />
<arg value="/xml=UnitTest-Main.xml" /> <!-- keep xml output -->
</exec>
然后,这些文件会在 ccnet.config 中“合并”。
<merge>
<files>
<!-- these file names need to conform to those found in default.build -->
<file>C:\cruisecontrol-dev\test\RegexDemo\UnitTest*.xml</file>
</files>
</merge>
CruiseControl.NET 识别来自 NUnit(以及许多其他应用程序)的 XML,并知道如何处理它。
Web 仪表板
一旦所有进程都在运行并且可见,您可以通过更改 dashboard.config 或构成其内容的 XML、XSL 和 CSS 来调整 CruiseControl.NET Web 仪表板。CruiseControl.NET 发送的电子邮件消息也以相同的方式控制,通过一组单独的文件。
摘要
总而言之,这里概述的构建过程配置在三个地方:CruiseControl.NET 的 ccnet.config、NAnt 的 default.build 以及解决方案本身。CruiseControl 是一个很棒的系统,我们在最初几周就已经发现了它意想不到的用途。我仍然对其灵活性印象深刻。
示例代码
示例代码包含一个 ccnet.config 的示例,该文件构建了一个简单的应用程序,带有一个单元测试且没有异常依赖项。该示例应用程序可以签入 CVS 并用于测试。default.build 文件也包含在内。