为什么要持续集成? 在没有应用持续集成之前,传统的开发模式是项目一开始就划分模块,然后等所有的代码都开发完成之后再集成到一起进行测试,随着软件技术的发展,各种软件方法百花齐放,软件规模也在扩大,软件需求越来越复杂,软件已经不能简单地通过划分模块的方式来开发,需要项目内部互相合作,划 分模块这种传统的模式的弊端也越来越明显,由于很多 bug 在项目的早期就存在,到最后集成的时候才发现问题,开发者需要在集成阶段花费大量的时间来寻找 bug 的根源,加上软件的复杂性,问题的根源很难定位,甚至出现不得不调整底层架构的情况,在这个阶段的除虫会议(bug meetings)特别多,会议的内容基本上都是讨论 bug 是怎么产生的,最后往往发展成为不同模块的负责人互相推诿责任。 持续集成最大的优点是可以避免这种传统模式在集成阶段的除虫会议。持续集成主张项目的开发人员频繁的将他们对源码的修改提交(check in)到一个单一的源码库,并验证这些改变是否对项目带来了破坏,持续集成包括以下几大要点:访问单一源码库,将所有的源代码保存在单一的地点(源码控制系统), 让所有人都能从这里获取最新的源代码(以及以前的版本)。 支持自动化创建脚本,使 创建过程完全自动化,让任何人都可以只输入一条命令就完成系统的创建。 测试完全自动化,要求开发人员提供自测试的代码,让 任何人都可以只输入一条命令就运行一套完整的系统测试。 提供主创建,让任何人都可以只输入一条命令就可以开始主创建。 提倡开发人员频繁的提交(check in)修改过的代码。 持续集成的关键是完全的自动化,读取源代码、编译、连接、测试,整个创建过程都应该自动完成。对于一次成功的创建,要求在这个自动化过程中的每一步都不能出错,而最重要的一步是测试,只有最后通过测试的创建才是成功的创建。 在持续集成里面创建不再只是传统的编译和连接那么简单,创建还应该包括自测试,自测试的代码是开发人员提交源码的时候同时提交的,是针对源码的单元测试(源自 XP 的实践),将所有的这些自测试代码整合到一起形成测试集,在 所有的最新的源码通过编译和连接之后还必须通过这个测试集的测试才算是成功的创建。这 种测试的主要目的是为了验证创建的正确性,M cConnell 称之为“冒烟测试”,在 持续集成里面,这 叫做集成验收测试Build Verify Test,简称 BVT。BVT 测试是质量的基础,QA 小组不会感受到 BVT 的存在,他们只针对成功的创建进行测试(如功能测试)。 BVT 测试应该尽量的详尽,详尽的测试才能发现更多的问题,而由此得到的反馈结果也更有参考意义,测试应该全部执行完毕,这样得到的反馈结果才是完整的,而不是遇到错误就放弃测试过程。 持续集成和日创建相比还有以下特点: 持续集成强调了集成频率,和日创建相比,持续集成显得更加频繁,目前推荐的最佳实践是每一个小时就集成一次。 持续集成强调及时反馈,日创建的目的是得到一个可以使用的稳定的发布版本,而持续集成强调的是集成失败之后向开发人员提供快速的反馈,当 然成功创建的结果也是得到稳定的版本。 日创建并没有强调开发人员提交(check in)源码的频率,而持续集成鼓励并支持开发人员尽快的提交对源码的修改并得到尽快的反馈。 从上面列出的续集成和日创建相比的特点来看,很明显,“ 频率”和“反馈”这两个词出现的特别多,持 续集成有一个与直觉相悖的基本要点,那 就是“ 经常性的集成比偶尔集成要好”。Martin Fowler 认为对于持续集成来说,集成越频繁,效果越好 ,如果你的集成不是经常进行的(少于每天一次),那么集成就是一件痛苦的事情,如果集成偶尔才进行一次(一周甚至一个月), 等到集成阶段发现bug,然后找原因解决bug,会耗费你大量的时间与精力,而且这种方式有点象传统的集成模式,这违背了持续集成的初衷。 根据Martin Fowler 的观点,项目 bug 的增加和时间并不是线性增长的关系,而是和时间的平方成正比,两次集成间隔的时间越长,bug 增加的数量越超过你的预期,解决 bug 付出的工作量也越大,而你越觉得付出的工作量越大,你就越想推迟到以后去集成,企图到最后一次性解决问题,结果 bug 产生的就更多,导致下一次集成的工作量更大,你越感觉到集成的痛苦,就越将集成的时间推后,最后形成恶性循环。 因此如果集成的结果是让你感到痛苦,也许就说明你应该更频繁地进行集成。频繁的集成和及时的反馈鞭策着项目小组积极的面对问题,而 不是将问题推到最后来解决,如 果方法正确,更频繁的集成应该能减少你的痛苦,让你节约大量时间。 因为持续集成最终是通过测试来验证创建,所以你会发现对于持续集成的频率的要求跟Kent Beck 提出的测试驱动的开发方法里面测试第一的理念完全一致。需要注意的是从项目的一开始就引入持续集成可以尽早的发现 bug,但是并不代表持续集成可以帮你你抓到所有的 bug。持续集成的排错能力取决于测试技术,众所周知,无法证明已经经过测试的代码就已经找到了所有的错误。 前面列举了持续集成这么多优点,但是创建一个持续集成的环境技术上是比较复杂的,也需要一定的时间,关键是在于持续集成可以“及时”抓到足够多的 bug,从根本上消除传统模式的弊端,这就已经很值得为在它上所花费的开销了。