转载自:http://www.oschina.net/p/buildbot
使用 Buildot 实现持续集成
使用基于 Python 的工具实现持续集成的理论与实践
牛仔式编码的日子在大多数组织中早已不复存在,由一种优质软件创建新潮所取代。持续集成(CI)测试是敏捷的编程方法实践中一个至关重要的部分,能够实现高品质软件。通过探索 Buildbot 来学习 CI 测试的理论和实践,Buildbot 是用 Python 编写的一个开源 CI 系统。
持续集成(CI)是发扬以下原则的一个软件开发流程:
维护单源存储库
自动化构建过程
实现自测试构建
每个人每天都有贡献
每一份贡献都应用于在一个集成机上构建主线
加快构建过程
在一个相同的生产环境中执行测试
使任何人都可以简单获取最新的可执行文件
每个人都可以看到当前状况
自动化部署
经 Martin Fowler 大力普及,CI 的基本理念就是持续测试并构建每个分支程序和将分支代码合并后的软件。这可以从总体上提高代码库的健康状况。还可以增加与团队成员的交流,并有机会获取对代码整体质量的反馈。人们通常使用这个周期来生成代码覆盖报告和其他统计信息。
Buildbot 类似于其他 CI 系统,有助于自动化这个检查、构建和测试流程。Buildbot slaves 通常运行于不同的平台,比如 Win32、Solaris、Intelx64 等。当一个构建(build)中断时,Buildbot 可以发送一个电子邮件通知,它追踪所有运行中的构建,这样开发人员就可以鸟瞰整个流程。最后,人们常常利用自动化周期构建既定时间内软件质量的度量标准。本文结尾将谈及该度量标准以及在一个 CI 系统内运行它们的原因。
Buildbot 简介
在我们深入探讨 Buildbot 之前,先看一下其架构。如图 1 所示,在构建流程的顶部主要有三个层。首先是一个版本控制层,它从一个版本控制系统钩入通知。其次是一个构建层,它从构建主服务器那里获取通信,并返回构建结果。最后是一个通知层,用于在构建失败时发送电子邮件或一个 IRC 消息,或让一个 web 页面显示构建的累积结果。
图 1. Buildbot 架构概览
Buildbot 架构的中心特性之一是对基于 Python 的 Twisted 库的依赖性,用于处理主服务器(master)和伺服机(slave)之间的异步通信。这个基于回调的架构支持一个很简单、但健壮的主/伺服反馈圈。在本文后面的 参考资料 部分可以找到有关 Twisted 的更多信息。
如果您尚未听说过 Buildbot,在 Google 上搜索一下就会找到大量与大小开源项目相关的主服务器和伺服机。关于伺服机,我在前面简单地提及了一下,它本义上是一个由主 Buildbot 服务器控制的伺服机器。一般来讲,一个伺服机是多个运行不同测试平台的伺服机之一。这是 Buildbot 服务器中一个很重要的概念。例如,您可能在一个开源项目的邮件列表上,听到有人说,“有人自愿充当 Windows 伺服机的虚拟机吗?”
Python 语言项目本身使用大量 Buildbot 伺服机,在尽可能多的平台上持续构建和测试最新版的 Python。图 2 显示了运行 Python 主干的许多伺服机以及测试。随着虚拟化技术的发展,现在可以常常要求开发社区成员托管一个 Buildbot 伺服机,或仅仅运行模拟不同硬件配置的几个虚拟机。
图 2. Python Buildbot;参见 放大图
另一个备受瞩目的 Buildbot 用户是 Google Chrome 浏览器项目。图 3 显示了一个高度定制的 Buildbot,它极大地增强了 Buildbot 用户界面的外观。幸运的是,Google 将这些增强的开放代码提供给 Buildbot,从下面的 参考资料 部分,您可以获取源代码并构建这个定制版本。
图 3. Google Chrome 增强的 Buildbot;参见 放大图
构建这个配置不在本文讨论范围内,但是我建议您自己看一下。现在我们看一下如何使一个 Buildbot 主服务器快速运转起来。
5 分钟内设置 Buildbot
我在 Ubuntu 8.10 上执行了这几步,不过它们应该在大部分 Linux 系统上都适用:
- 下载 ez_setup.py:
wget http://peak.telecommunity.com/dist/ez_setup.py
- 安装 easy_install:
sudo python ez_setup.py
- 使用 apt-get 安装 Python Twisted 包
sudo apt-get install python-Twisted
- 遵循这个 collective.buildbot “秘诀”:
sudo easy_install collective.buildbot
此时,许多东西开始涌出 shell,因为有一大堆包被下载且得到自动安装。完成这些步骤之后,就可以开始创建 Buildbot 了!如果安装过程进行得很顺利,在 shell 提示符处输入:
$ paster create -t buildbot my.project $ cd my.project
现在设置已经快完成了,但在完成之前,我要提几个在首次配置 Buildbot 时您容易出错的地方。在您的 my.project/master.cfg 文件中,应该可以看到以下内容:
清单 1. master.cfg 内容
[buildout] master-parts = master passing.project # uncomment this to enable polling poller [master] recipe = collective.buildbot:master project-name = passing.project project # allow to force build with the web interface allow-force = true # internal port port = 9051 # http port wport = 9081 # buildbot url. change this if you use a virtualhost url = http://localhost:9081/ # static files public-html = ${buildout:directory}/public_html slaves = localhost NaOaPSWb [passing.project] recipe = collective.buildbot:project slave-names = localhost vcs = hg repositories = /home/ngift/myhgrepo # notifications mail-host = localhost email-notification-sender = buildbot@cortese email-notification-recipient = super@example.com # run test each hour periodic-scheduler=60 # cron build cron-scheduler = 0 8 * * * # You can change the sequences to build / test your app # default options should work for most buildout based projects build-sequence = # /usr/bin/python2.5 bootstrap.py -c project.cfg # /usr/bin/python2.5 bin/buildout -c project.cfg test-sequence = nosetests # zope.testing require exit with status # bin/test --exit-with-status [poller] recipe = collective.buildbot:poller # don‘t forget to check this # since it‘s generated from the paster template it may be a wrong url repositories = /home/ngift/myhgrepo #user = h4x0r #password = passwd poll-interval = 120
最初检查最重要的内容是确保有合适的源控制存储库,一开始将 build-sequence
留空,当代码迁出您为它提供的存储库时,您的 test-sequence
(在我的例子中是
“nose”)会通过测试。如果您有其他问题,请查阅 collective.buildbot 资源指南(参阅 参考资料 对该指南的链接)。
设置好配置文件之后,只需运行下面两个命令:
$ python bootstrap.py $ ./bin/buildout
在运行 buildout
命令时,您会看到以下输出:
清单 2. buildout 命令的输出
{673} > ./bin/buildout Unused options for buildout: ‘master-parts‘. Installing master. New python executable in /home/ngift/my.project Installing setuptools............done. [output suppressed for space]
该命令结束之后,您就完成了 Buildbot 的安装,现在就可以使用它了。运行以下 shell 命令启动 Buildbot 守护进程:
$ ./bin/master start $ ./bin/yourhostname start
如果您在浏览器中输入在主 .cfg 文件中设置的 URL,默认情况下为 http://localhost:9081/,您会看到全新的 Buildbot。当然,它现在可能还没有多少功能。如果您为它提供一个构建脚本和一个测试运行程序,它会很乐意检查、构建并自动测试您的代码。当然,您稍后应当浏览一些配置选项,但最难的部分已经完成了。
生成代码度量报告
“测试迷” 中一个最新的智能开发,是要利用持续集成周期来生成有关源代码的度量。其中一种最流行的方法是运行带既定选项的 nosetest 测试收集器。如果您有一个名为 “foo” 的项目,您通常会运行:
nosetests --with-coverage --cover-package=example --cover-html \
--cover-html-dir=example_report.html test_example.py
这会生成一个 HTML 报告,显示未涉及的所有代码行,以及类似于清单 3 的 stdout 的输出:
清单 3. nosetest 输出
nglep% nosetests --with-coverage --cover-package=example --cover-html-dir=example_report.html test_example.py . Name Stmts Exec Cover Missing --------------------------------------- example 2 2 100% ---------------------------------------------------------------------- Ran 1 test in 0.004s OK
您可以从 下载 部分下载 example.py 和 test_example.py。
每次修改代码后都运行这个报告,为开发人员和管理人员提供有关代码变化的元数据。这是展示为何同时运行度量标准的一个绝佳例子,因为 CI 对一个项目有好处。
另一个提供代码元数据的度量工具是 PyMetrics 的 McCabe 评定。早在20 世纪 70 年代,Thomas McCabe 就提出一个简单、但独创性的代码观察结论:一段代码越复杂,它中断的可能性就越大。这虽然看起来很明显,但遗憾的是,很多开发人员似乎看不到其中的联系。使用 PyMetrics 的命令行工具,您可以确定每个函数的分支数。
通常,您希望将编写的每个方法或函数的分支数保持在 10 以下,因为在人脑中保留 7 或 8 份内容很难。类似的,大于 50 段的代码基本上是无法测试/无法维护的。
我就亲眼看到过 140 多段的代码,代码很差,它确实验证了 McCabe 的理论。如果您可以在开发前期捕获和标记这个复杂、脆弱的代码,那么即使所有测试都通过,它也不会出现在生产环境中。
结束语
持续集成的主要优势是,能够通过软件的自动化构建以及测试和软件度量标准(可选)精简品质保证周期。每次更改源代码并为项目生命期提供即时反馈和报告时,都会触发构建。当 CI 得到正确配置时,它实际上就集成到代码生成过程中,如同亲自参与编写代码一样。
Buildbot 并非用于 CI 测试的惟一工具。您也可以了解一下 Hudson 和 Bitten。它们都支持使用 Python 插件进行定制,即使 Hudson 是用 Python 编写的。参阅以下的参考资料,详细了解这些系统相关内容。