BitbucketのPull Requestをテストする


2013年 06月 17日

プルリクエスト(Pull Request)、とても便利な仕組みですよね。
マージがボタン一つでできますし、ソースコードレビューも格段にやりやすくなったと感じています。

私の所属しているプロジェクトでは、Bitbucketのプルリクエストを使ってソースコードレビューを行っています。

プルリクエストは、全体テストを一回手元で通してから送るのがマナー です。
そうでないと、レビューアーが問題なしと判断してマージボタンを押した後に、

  • デグレが発生しており、テストが一部通らなくなっている
  • typoがあって、そもそもコンパイルが通らない状態になっている

といった問題が発覚することがあります。結構よく起こります。

もちろん、Jenkins等のCIツールを使っているので、問題はすぐに発覚します。
しかし、問題を修正するまではソースをpullできない状態になるわけで、他の開発者に迷惑をかけてしまいます。

「テスト通してからプルリクエスト出すとか、あたりまえじゃん」と思われるかもしれません。
しかし、毎日スケジュールに追われながら開発をしていると、そんな当たり前のこともしなくなってしまうものです。どうしたものか。何か解決策は無いものでしょうか。

なぜ全体テストを通さず、プルリクエストを出すようになったのか

私たちのプロジェクトでも、初期の頃は全体テストを手元で通してからプルリクエストを送っていました。
しかし、プロジェクトが進むにつれて、以下の問題が発生しました。

  • spec(テストケース)が多すぎて、全体テストを手元で実行するには時間がかかりすぎる
  • テストに時間がかかるので、「今書いた処理のspecだけ実行してから、プルリクエスト出そう。」と考えるようになり、実践する

私たちのプロジェクトで全体テスト実行がどのくらいかかるのか。Jenkinsでテストを実行したときのビルド時間は下図のような感じです。

1bdc92c2-f60e-79b5-c4dc-9b4bbdd11025.png

マシンが遅い、他のJobも一緒に走っているため、開発環境で動かしたときよりも若干遅いなど要因が他にもありますが、それでも1時間56分はかかりすぎです。

ローカル開発環境で、全体テストを走らせている間は、ただでさえ遅い開発マシンがより一層おそくなります。

我々は常にスケジュールに追われています。その間開発が止まるとなると時間の無駄です。
そうなると、もはや全体テストを手元で実行するのは面倒になり、結果として、

  1. 十分なテストをせずプルリクエスト
  2. レビューアーも疲れているのでそのままマージ
  3. Jenkinsが怒る
  4. 「え、今テスト直すの? 他の作業してるし、後で直すよ」

となり、そのままテストの失敗した状態がしばらく続くという最悪の事態となります。

プルリクエストに対してテストを実行する

この問題を防ぐためには、プルリクエストを出した段階で、そのプルリクエストに対しテストを実行してくれるような仕組みがあればよいわけです。
ついでにコメントとしてテスト結果もかいておいてくれるとよいですね!

Githubを使っている方々。よかったですね。既にその仕組みはあります。
Jenkinsからプルリクエストをテストするなら、Github pull request builder plugin で実現できます。
GithubはAPI経由でプルリクエストの情報を取得できるので、

  1. Jenkinsからプルリクエスト一覧取得
  2. まだテストしていないプルリクエストをテスト
  3. 結果をCommit Status API経由で書き込み

ということができます。

さて、Bitbucketにもその仕組みが欲しいですね。残念。BitbucketはAPI経由でプルリクエスト一覧を取得する仕組みがないのです( 2013/6/9時点 )。
Pull Request APIの要望はあがっているのですが、いつ実装されるのかが不明です。
実装されるまで待てない、いまさらGithubに移行なんてできない。

なければ作ればいいじゃないか!

ということで作ってGem bitbucket-api-extension として公開しました。

使い方の詳細などはここでは説明しませんが、上記gemを利用することで、プルリクエストの一覧取得、プルリクエストの詳細情報(revision, branchの情報等) が取得できます。

プルリクエスト一覧さえ取得できてしまえば、あとはJenkinsマシンでテストするだけです。わざわざ図にするほどのものではないですが、イメージとしては下図のような感じです。

sys60456cc.png

我々のプロジェクトでは、 PRTester というプルリクエストテストのためのプログラムを作りました。
まったく汎用的ではありませんので、他のプロジェクトでは使えないと思います。
ソースをみていただければわかると思いますが、コマンドをべた書きしてます。これはひどい。

テスト結果は下記のように、プルリクエストのコメントとして書き込まれます。

5aa8c7a7-730f-c257-1d54-b53295f99e8a.png

単純な仕組みですので、PRTesterみたいな簡単なスクリプトをご自分のプロジェクト用に作ってみてはいかがでしょうか。

PRTesterをしばらく運用してみて

プルリクエストもテストできるようになって問題解決!と思いきや、そうもいかず。
テスト実行が遅いという問題は相変わらず残っています。

一日に何個もプルリクエストが出される状態で、テストに1、2時間かかっているのでは、いつまでたってもテストされないプルリクエストがでてきてしまいます
そうなると、プルリクエストのテスト実行前にマージしてしまい、Jenkinsが怒りだすという事態も発生するようになってきました。最悪です。なんのためにPRTesterを作ったのか。

やはりテスト実行自体を早くする必要がありそうです。

ここからテスト実行を早くするための仕組みを検討しだすわけですが、それは次回紹介いたします。