Martin Fowler 的持续集成(2)

发表于:2012-12-21来源:博客园作者:无知者云点击数: 标签:持续集成
因此,做为最基本的持续集成实践,请保证你使用一款体面的代码管理系统。成本不是问题,有许多高质量的开源代码管理工具存在。当前的选择为Subve

  因此,做为最基本的持续集成实践,请保证你使用一款体面的代码管理系统。成本不是问题,有许多高质量的开源代码管理工具存在。当前的选择为Subversion(译者注:现在有了更新的hg和git)。(更老的开源工具CVS如今仍然被大量使用,虽然比没有强,但是Subversion是更现代的选择。)有趣的是,当我和一些开发者聊天时,我发现相比起多数商业化的代码管理系统,他们更喜欢Subversion。据我所知,唯一值得花钱买的只有Perforce。

  当你有了代码管理系统之后,确保每个开发者都能方便的获得到源代码。不应该有人还在问:“foo-whiffle 文件在哪儿?”所有东西都必须在代码库里。

  虽然许多团队都在使用代码库,但是我经常发现,他们并不把所有东西都放在里面。如果大家需要使用一个文件,他们知道该文件放到代码库中,但是,构建所需的所有都应该包含在代码库里,包括测试脚本,属性文件,数据库模式文件,安装脚本和第三方库等。我所知道的有项目将编译器加到代码库中的(对于早期脆弱的C++编译器来说非常重要)。基本原则是:在一台新机器上check out代码后构建也能构建成功。新机器上的东西应该尽量的少,通常包括很大的,难于安装的,并且稳定的软件,比如操作系统,Java开发环境或者数据库管理系统等。

  你需要将构建所需的所有东西都加到代码管理系统中,同时也需要将大家经常操作的东西方进去,IDE配置便是一个很好的例子,这样便于大家共享IDE配置。

  版本控制系统的一大功能是它允许你创建多个分支,以此来处理不同的“开发流”。这种功能很有用,但却经常被过度使用以至给开发者带来了不少麻烦。所以,你需要将分支的使用最小化,特别建议使用主线,即项目中只有单一的开发分支,并且每人在多数时间里都在“离线”工作。

  总之,你应该将构建所需的所有东西都放在代码管理系统中,而不应该将构建的输出放进去。有些朋友确实将构建输出放在代码管理系统中,但我认为这是一个坏味道,可能导致更深的问题——通常是你无法完成重新构建。

  使构建自动化

  将源代码变成一个能运行的软件系统通常是一个复杂的过程,包括编译,文件搬移,加载数据库模式等等。但其中大多数任务都是可以自动化的,并且也应该被自动化。让人去输入奇怪的命令或点击对话框是非常耗时的,而且从根本上来说也是个错误的做法。

  构建所需的自动化环境对于软件系统来说是一个通用功能。Unix的Make已经诞生好多年了,Java社区有Ant, .NET社区有Nant,现在又有了MSBuild。当你用这些工具构建和启动系统时,请确保只使用一个命令完成任务。

  一个常见的错误是在自动化构建里并没有完全包括构建所需的东西。构建过程中应该从代码库里取得数据库模式文件并自动执行之。结合我上文所讲的原则来看,任何人都应该能够在一台新机器上拉下代码库中的代码,并只用一个命令将系统运行起来。

  构建脚本是多种多样的,通常特定于某个平台或社区,但情况并不必须如此。我们的多数Java项目都使用Ant,而另外有些用Ruby(Ruby世界的Rake是一个非常不错的构建工具)。我们用Ant完成了早期的一个微软COM工程的构建自动化,并从中大获裨益。

  大型的构建通常需要很长的时间,而在你只做了很小的修改的情况下,你是不想运行所有的构建步骤的。因此,优秀的构建工具能够分析出哪些地方需要做相应的修改,并将这个分析过程本身做为整个构建过程的一部分。通常的做法是检查源代码和目标文件的修改日期,只有当源代码的修改日期晚于其对应的目标文件时才执行编译。依赖关系因此变得微妙起来了:如果一个目标文件发生了修改,那些依赖于它的文件也需要重新构建。有些编译器能够处理这种依赖关系,而有些就不见得。

  根据自己的需要,你可以选择不同的东西进行构建。构建中既可以包括测试,也可以不包括,甚至可以包括不同的测试板块。有些组件可以进行单独构建。构建脚本应该能够允许你针对不同的情形进行不同的构建目标。

  我们大多数都使用IDE,而多数IDE都或多或少地集成了构建管理功能。但是这样构建文件通常是特定于IDE的,而且非常脆弱。此外,它们需要依赖于IDE才能工作。虽然对于开发者个人来说,在IDE中做这样的构建配置并无不妥,但对于持续集成服务器来说,一份能够被其它脚本调用的主构建脚本却是至关重要的。比如一个Java项目,各个开发者可以在自己的IDE中进行构建,但应该还有一个Ant主构建脚本来保证构建能在集成服务器上顺利完成。

  使构建自测试

  传统意义上的构建包括只编译,链接等过程。此时程序也许能运行起来,但这并不意味着系统就能正确地运行。虽然现在的静态语言已经能够捕捉到许多bug,但是漏网之鱼却更多。

  一种快速并高效发现bug的方法是将自动化测试包含到构建过程中。当然,测试也不见得完美,但的确能发现很多bug——足够多了。特别是随着极限编程(XP)的升温,测试驱动开发(TDD)也使自测试代码流行起来,越来越多的人开始注意到这种技术的价值所在。

  经常读我著作的读者可能知道我是一个TDD和XP的大粉丝,然而我想强调的是这两种方法和自测试并没有必然联系。TDD和XP都要求先写测试代码,再写功能代码使测试通过。在这种模式下,测试既用于发现bug,又用于完成系统设计。这是非常好的,但对于持续集成来说不必如此,因为此时我们自测试代码的要求并不那么高。(然而TDD是我写自测试代码的首选。)

  对于自测试代码而言,你需要一组自动化测试来检测一大部分代码库中的bug。测试能通过一个简单的命令来运行并且具备自检功能。测试的结果应该能指出哪些测试是失败的。对于自测试的构建来说,测试失败应导致构建失败。

  过去这些年里,TDD使开源的XUnit家族流行起来,成为了理想的测试工具。在ThoughtWorks,XUnit已经是非常有用的测试工具,我也经常建议人们使用。这组工具起初由Kent Beck开发,它们使自测试环境的搭建变得非常简单。

  XUnit当之无愧地是你进行代码自测试的起点。当然,你也应当多看看那些更侧向于端到端测试的工具,包括FIT,Selenium,Sahi,Watir,FITnesse等等,我就不逐一列举了。

原文转自:http://www.ltesting.net