Buildbot による継続的インテグレーション

Python ベースのツールを使った継続的インテグレーションの理論と実践

ほとんどの組織では、カウボーイ・コーディングをしていた日々は遠く過ぎ去り、今では高品質のソフトウェアを生成することに新たな関心が持たれています。高品質のソフトウェアを生み出すアジャイル・プログラミング手法を実践する上で、CI (Continuous Integration: 継続的インテグレーション) テストは不可欠な要素です。Python で作成されたオープンソースの CI システムである Buildbot を試しながら、CI テストの理論と実践を学びましょう。

Noah Gift , Senior Technical Director, GiftCS, LLC

Photo of Noah Gift

Noah Gift は O'Reilly から出版されている『Python For Unix and Linux System Administration』の共著者であり、また Manning から出版予定の『Google App Engine In Action』も執筆中です。彼は著作者、講演者、コンサルタント、そしてコミュニティーのリーダーとして、Red Hat MagazineO'ReillyMacTech などに記事を寄稿しています。彼のコンサルティング会社の Web サイトは http://www.giftcs.com であり、彼が寄稿した記事の大部分は http://noahgift.com で公開されています。Twitter で Noah をフォローすることもできます。

彼はカリフォルニア州立大学ロサンゼルス校でコンピューター情報システムの修士号を、カリフォルニア州立工科大学 San Luis Obispo 校で栄養科学の学位を取得しています。また、Apple と LPI 認定のシステム管理者であり、Caltech、Disney Feature Animation、Sony Imageworks、Turner Studios、Weta Digital などの企業に勤務経験があります。仕事以外の時間には彼の妻である Leah と息子の Liam と時間を過ごし、ピアノ曲を作曲し、マラソンをし、そして神に祈りを捧げています。



2010年 6月 02日

CI (Continuous Integration: 継続的インテグレーション) は以下の原則を推進するソフトウェア開発プロセスです。

  • ソース・リポジトリーを 1 つに維持する
  • ビルドを自動化する
  • ビルドによって自己テストを行う
  • 毎日、全員がコミットする
  • コミットするごとに、統合マシンの主系がビルドされるようにする
  • ビルドを高速に維持する
  • 本番環境のクローンでテストする
  • 最新の実行可能ファイルを全員が容易に入手できるようにする
  • 何が起きているのかが全員にわかるようにする
  • デプロイメントを自動化する

主に Martin Fowler によって広められた CI の基本概念では、ブランチごとに、またコードをトランクにマージするごとに、継続的にテストとビルドを行います。こうすることで、コード・ベース全体としての健全さを高めることができます。また、チーム・メンバー間のコミュニケーションが活発になり、コードの全体的品質に対するフィードバックを得やすくなります。開発者はこのサイクルを利用して、コード・カバレッジ・レポートやその他の統計を生成することがよくあります。

Buildbot は他の CI システムと同様、このチェックアウト、ビルド、テストというサイクルの自動化を支援します。Buildbot スレーブは通常、Win32、Solaris、Intelx64 など、さまざまなプラットフォーム上で実行されます。Buildbot はビルドで障害が起きると E メールで通知し、また実行中のすべてのビルドを追跡します。そのため開発者はプロセス全体の状況を高い視点から把握することができます。また、この自動サイクルを利用して、いつでもソフトウェア品質に関するメトリクスを生成することができます。この記事の最後ではメトリクスを取り上げ、なぜ CI システムの中でメトリクスを実行することに意味があるのかを説明します。

Buildbot の紹介

Buildbot の概要を説明するにあたり、まずは Buildbot のアーキテクチャーを見てみましょう。図 1 に示すように、基本的にビルド・プロセスの上に 3 つのレイヤーがあります。バージョン管理レイヤーは、バージョン管理システムからの通知にフックされます。ビルド・レイヤーは、ビルド・マスターからの通信を受信し、ビルドの結果を返します。最後に、通知レイヤーがあります。通知レイヤーは多くの場合、ビルドが失敗した場合に E メール (つまり IRC メッセージ) を送信するように、またはそれまでに収集したビルドの結果を Web ページに表示するように構成されます。

図 1. Buildbot のアーキテクチャーの概要
Buildbot のアーキテクチャーの概要

これら以外に Buildbot のアーキテクチャーの中心的な特徴の 1 つとして、Python ベースの Twisted ライブラリーを利用してマスター/スレーブ間の非同期通信を処理しています。このコールバック・ベースのアーキテクチャーを使用することで、非常に単純ながら堅牢なマスター/スレーブ型のフィードバック・ループを構成することができます。Twisted の詳細については、この記事の最後に挙げた「参考文献」セクションを参照してください。

今まで Buildbot について聞いたことがなくても、Google で少し検索してみると、大小さまざまなオープンソース・プロジェクトに関連して大量のマスターやスレーブがあることがわかります。スレーブについては先ほど簡単に触れましたが、スレーブというのは文字どおりマスター Buildbot サーバーに制御されるスレーブ・マシンです。通常、1 つのスレーブは、互いに異なるテスト・プラットフォームを実行する何台かのスレーブ群のうちの 1 台です。これは Buildbot サーバーの世界の重要な概念です。例えば、あるオープンソース・プロジェクトのメーリング・リストに皆さんが登録しており、誰かが「Windows スレーブ用の仮想マシンを誰か自発的に提供してくれませんか」と発言するのを聞く、という状況と似ています。

Python 言語プロジェクト自体が大量の Buildbot スレーブを使用し、可能な限り多くのプラットフォーム上で、最新バージョンの Python のビルドとテストを継続的に行っています。図 2 には多種多様なマシンが表示されていますが、これらのマシンは Python トランクに対するスレーブ・ビルドやテストを実行しています。最近の仮想化の進歩により、開発コミュニティーのメンバーに Buildbot スレーブをホストするように依頼したり、あるいは多様なハードウェア構成をエミュレートするために、単に何台かの仮想マシンを実行するように依頼したりすることは、今では一般的になっています。

図 2. Python での Buildbot:

クリックして大きなイメージを見る

図 2. Python での Buildbot:

Buildbot のユーザーとしては、Google の Chrome ブラウザー・プロジェクトも有名です。図 3 は大きくカスタマイズしたバージョンの Buildbot です。このバージョンでは Buildbot のユーザー・インターフェースのルック・アンド・フィールが大きく改善されています。幸いなことに、Google はこうした機能強化をオープンソースとして Buildbot に提供しました。また、このカスタマイズ・バージョンのソースとビルドを下記の「参考文献」セクションから入手することができます。

図 3. Google Chrome 用に機能強化された Buildbot:

クリックして大きなイメージを見る

図 3. Google Chrome 用に機能強化された Buildbot:

この記事では、この特定の構成をビルドする方法については省略しますが、皆さん自身で試してみるようお勧めします。今度は Buildbot マスター・サーバーを素早く動作させてみましょう。


Buildbot を 5 分でセットアップする

私は Ubuntu 8.10 で下記のステップを実行しましたが、大部分の Linux ディストリビューションでもステップは同じはずです。

  1. 下記を実行して ez_setup.py をダウンロードします。
    wget http://peak.telecommunity.com/dist/ez_setup.py
  2. 下記を実行して easy_install をインストールします。
    sudo python ez_setup.py
  3. 下記を実行して apt-get を使って Python Twisted パッケージをインストールします。
    sudo apt-get install python-Twisted
  4. 下記を実行して collective.buildbot の「レシピ」を実行します。
    sudo easy_install collective.buildbot

この時点で、大量のパッケージが自動的にダウンロードされてインストールされ、シェルから大量の内容が生成されます。それが終了すると、Buildbot の作成準備は完了です。インストールが適切に終了したら、シェル・プロンプトから下記を入力します。

$ 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 のリソース・ガイドを見てください (「参考文献」のリンクを参照)。

構成ファイルを設定できたら、単純に下記の 2 つのコマンドを実行します。

$ python bootstrap.py
$ ./bin/buildout

buildout コマンドを実行すると、リスト 2 のような出力が大量に生成されます。

リスト 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 のインストールは完了し、起動準備が整ったことになります。シェルから下記のコマンドを実行し、両方の Buildbot デーモンを起動します。

$ ./bin/master start $ ./bin/yourhostname start

次に、master.cfg ファイルの中で設定した URL (デフォルトは http://localhost:9081/) にブラウザーでアクセスすると、Buildbot が華々しく表示されます。もちろん、この状態では大したことはできません。Buildbot にビルド・スクリプトとテスト・ランナーを指定すると、Buildbot はコードをチェックアウトし、そのコードを自動的にテストします。もちろん、後で構成オプションをいくつか詳細に調べる必要はありますが、面倒な作業は基本的に終わりです。


コードのメトリクス・レポートを生成する

最近、「テストおたく」の間では、ソース・コードに関するメトリクスの生成にも CI サイクルを利用するようになり、知的な進歩を遂げています。最もよく使われる手法は、カバレッジ・オプションと組み合わせて nosetest テスト・コレクターを実行する方法です。例えば「foo」という名前のプロジェクトがあったとすると、通常は下記を実行します。

nosetests --with-coverage --cover-package=example --cover-html \
--cover-html-dir=example_report.html test_example.py

この結果、カバーされなかったコード行すべてを表示する HTML レポートと、下記のような 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 と同時にメトリクスを実行することがプロジェクトにとって意味があるかを示す完璧な例です。

コードに関するメタデータを得るための、もう 1 つのメトリクス・ツールが PyMetrics の McCabe レーティングです。今をさかのぼる 1970 年代、Thomas McCabe は、コードに関して単純ながら独創的な観察を行い、コードが複雑であればあるほどコードに問題が起こりやすいことに気が付きました。これは当然に思えるかもしれませんが、残念ながら多くの開発者はその関係に気付いていないようです。PyMetrics コマンドライン・ツールを使うことで、関数当たりのブランチの総数を知ることができます。

通常、作成するメソッドや関数それぞれのブランチの総数を 10 未満に維持する必要があります。人間の脳では、一度に 7 つか 8 つを超える事項を筋道立てて考え続けることは困難だからです。比較の参考として、スコアが 50 を超えるコードは基本的にテスト不能で保守不能です。

私は、本番コードで 140 という高いスコアを見たことがあり、そのコードは非常に質の悪いものでした。つまりそのコードは実際に McCabe の理論を実証していました。こうした複雑で脆弱なコードを開発プロセスの初期に見つけ、フラグを立てておけば、たとえすべてのテストにパスしたとしても、そうしたコードが本番コードに入り込むことはありません。


まとめ

CI の主な利点は、ソフトウェアのビルドとテストの自動化や、ソフトウェア・メトリクスを自動生成するオプションなどにより、品質保証サイクルを効率化できることです。プロジェクトの存続中、こうした自動ビルドはソースが変更されるごとにトリガーされ、瞬時にフィードバックとレポートが返されます。実際、CI が適切に構成されると、コードそのものを作成するプロセスの中に CI が組み込まれるだけではなく、コードを make するプロセスにも CI が組み込まれるようになります。

CI テストに使用できるツールは Buildbot のみではありません。Hudson や Bitten も調べてみる必要があります。これらはどれも、Python によるプラグインを使ってカスタマイズすることができます (ただし Hudson は Python で作成されています)。これらのシステムの詳細については「参考文献」セクションの資料を参照してください。


ダウンロード

内容ファイル名サイズ
Sample Python scriptsexample.zip1KB

参考文献

学ぶために

製品や技術を入手するために

  • Google Chrome Buildbot のソースを入手してください。
  • Buildbot に代わるものとして、HudsonBitten を調べてみてください。
  • nose テスト・フレームワークに関して学んでください。
  • collective.buildbot サイトには、Buildbot の「buildout」レシピが集められています。
  • PyMetrics は循環的複雑度 (Cyclomatic Complexity) スコアを生成するためのツールです。
  • 皆さんの目的に最適な方法で IBM 製品を評価してください。製品の試用版をダウンロードする方法、オンラインで製品を試す方法、クラウド環境で製品を使う方法、あるいは SOA Sandbox で数時間を費やし、サービス指向アーキテクチャーの効率的な実装方法を学ぶ方法などがあります。

議論するために

  • My developerWorks コミュニティーに加わってください。開発者向けのブログ、フォーラム、グループ、ウィキなど利用しながら、他の developerWorks ユーザーとやり取りしてください。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux, Open source
ArticleID=498218
ArticleTitle=Buildbot による継続的インテグレーション
publish-date=06022010