mixiエンジニアがおくるソーシャルアプリ開発実践講座

第3回 自動テストと継続的インテグレーションを既存プロジェクトへ導入しよう

この記事を読むのに必要な時間:およそ 3 分

継続的インテグレーション

すべての(実際にはブラックリストに列挙されているものだけを除いた)テストが実行できるようになると,その実行時間が問題になり始めました。遅いテストの終了を待つのは苦痛で,しばしば実行せずに済まされがちです。mixiでも,安定版からのブランチで発見したテストの失敗が,実は安定版の時点で発生していた,ということが時折ありました。すべてのマージごとにすべてのテストを実行すれば,このような問題は防げていたはずです。

そこで導入したのが継続的インテグレーションのしくみです。mixiでは最初にBuildbotを導入し,現在はJenkinsを使っています。Jenkinsは安定版へのコミットを定期的に監視し,変更があった場合にビルドを実行,結果を社内IRCのチャネルに書き込みます。なお,Jenkinsの用語に合わせて「ビルド」という語を使いましたが,mixiの場合の「ビルド」は,単に自動テストの実行を指しています。

mixiの自動テストは非常に遅く,現在,実行に15分程度の時間を要します。そこで,コミット直後には「今のコミットに含まれるテストと,関連するファイルのテスト」だけを実行するしくみを別途用意しています。mixiでは,コードとテストのファイル名に「lib/Mixi/Foo.pmのテストは,t/lib/Mixi/Foo.tあるいはt/lib/Mixi/Foo/以下に存在する」というゆるやかなルールがあるため,関連するファイルもこのルールを使って探しています。

この「今のコミットに含まれるテストと,関連するファイルのテスト」はたいてい30秒もかからずに終了し,これが成功した場合のみ,全体のテストが走り出します。このしくみによって,15分もかかるテストが,コミット時にファイルを追加し忘れた,といったくだらないミスで失敗することを防いでいます。

説明の都合上,まず開発者テスト,次に継続的インテグレーションという順になりましたが,実際には,この2つは並行して導入を進めていました。継続的インテグレーションの存在は,⁠テストを書いたけど誰も実行してくれない」という問題を軽減します。CやJavaで書かれたソフトウェアなら,ビルドの依存関係の片隅にテストの実行を忍ばせることも可能ですが,スクリプト言語の場合そうはいきません。少なくともmixiの場合はそうでした。また,IRCにテストの失敗を通知し,実際にリリース版でも問題が見つかるという流れは,自動テストの認知向上につながったと思います。

任意のブランチをテストする

mixiでは,trunkを安定版とし,すべての変更をブランチを作って行うルールで運用しているため,リポジトリ上には大量にブランチが存在しています。一方,Jenkinsが定期的にテストを実行しているのは,安定版と,複数の人々が長期で関わる大きなプロジェクトのブランチだけです。その他の多くのブランチでは,普段は自分の開発環境で,自分が変更した部分に関連したテストだけを実行し,必要に応じてJenkins上で全テストを実行する,という運用がされています。

Jenkinsで実行できるテストは,開発環境で実行できるものと変わりません。ただ,開発環境はJenkinsで使っているものと同様のスペックのものを仮想化して分割しているため,あまり速くありません。全テストの実行には,前述の15分よりさらに長い時間がかかってしまいます。

また,1つのVMの負荷が,物理的に同じホストに同居するほかのVMに影響してしまうという問題もあります。Jenkinsのホストならば,エディタやシェルのような対話的なソフトウェアはなく,負荷をあまり気にせずにかけられます。15分かかるテストの実行完了が16分になるのと,エディタの入力が一瞬遅れるのとでは,前者のほうが許容しやすいのではないでしょうか。

Jenkins上で任意のブランチをテストするために,mixiではParameterized Buildと呼ばれる,外部からパラメータをとってジョブを起動するしくみを使っています。まず,パラメータとしてブランチ名をとり,そのチェックアウトからテストまでを実行するジョブを作ります。開発者は,自分のテストしたいブランチをパラメータとして,このジョブを好きなタイミングで起動しています。

Parameterized Buildは,HTTPリクエストからパラメータ付きで起動できます。現在は「make remote-test」と打ち込むだけで,現在のワーキングコピーに対応するブランチのテストが,Jenkins上で実行されるようになっています。

まとめ

今回はmixiの自動テスト周辺の歩みについて,順を追って説明しました。

冒頭で述べたとおり,筆者は現在,こうした開発の裏側の改善をおもな業務としています。ただ,自動テストの導入から継続的インテグレーションの途中あたりまでは,お客様が直接目にするようなフロントエンドのアプリケーションの開発にも関わっていました。テストまわりの改善は,同じような不満を抱えた同僚と協力しながら行う,ボトムアップの仕事でした。

みなさんの中にも(少ないことを祈りますが⁠⁠,大きく,テストの手薄なコードベースを相手に,日夜格闘している方がいるかもしれません。高速な単体テストが無理なら,まず人の手を介さない自動テストから,差し替え用のモックオブジェクトを書く時間がないなら,まずデータベースの接続先を変えるところからと,徐々に歩みを進めていくことは可能です。今回の記事がそうした方々の一助になれば幸いです。

mixiでは開発エンジニアを募集しています。

詳細はこちら
http://career.mixi.co.jp/

著者プロフィール

加藤和良(かとうかずよし)

(株)ミクシィ システム本部技術部