2015-02-26

Google のバグ予測アルゴリズムと bugspots の導入

概要

はじめまして、開発の土田です。

Google のバグ予測アルゴリズム、というものがあります。

詳細は、「グーグルはコードの品質向上のため「バグ予測アルゴリズム」を採用している - Publickey」や、Google 本家の記事「Bug Prediction at Google - Google Engineering Tools」をご参照いただければ、と思いますが、基本的には「よくバグフィックスで更新されるファイルは危ない、最近のファイルほど危ない」という考え方です。バグフィックスのコミットに対して、古いものほど点数が低く、最近更新されたものほど点数が高くなるような計算式になっています。

また、このアルゴリズムを実装したオープンソースのツールである bugspotsというものもあります。こちらの詳細も Publickey の記事「グーグルのバグ予測アルゴリズムを実装したツール「bugspots」、オープンソースで公開 - Publickey」などをご覧いただければ、どんなものかイメージがつくのではないかと思います。

今回、この bugspots を導入したので、それについて書こうと思います。

bugspots の導入

bugspots の導入には cmake ruby が必要です。ruby の環境は rbenv で構築してみました。

rbenv の設定

rbenv をインストールします。(すでにインストール済みの場合はこの手順は不要です)

$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
$ source ~/.bashrc

ruby のインストール

ruby をインストールします。最新の 2.2 は手元の CentOS 6 ではうまくビルドができなかったので、2.1.5 を入れました。
最後の rbenv global はお好みで。(こちらの手順も、すでにインストール済みの場合は不要です)

$ rbenv install -list
...(インストール可能なバージョンを確認)
$ rbenv install 2.1.5
...(ruby 本体をコンパイルするので、結構時間がかかります)
$ rbenv global 2.1.5
$ ruby -v
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-linux]


bugspots のインストール

bugspots をインストールします。cmake が必要なので、インストールします。(インストール済みの場合は不要)

bugspots 自体は gem なので、簡単に入ります。

$ sudo yum install cmake
$ gem install bugspots

実行

対象は git リポジトリである必要があります。以下の例では、コミットログが「bug」で始まる変更を対象にしています。

cd 調べたいソースのディレクトリ
bugspots -r "/^*bug/" .

弊社がオープンソースとして提供している Malba というジョブキューのリポジトリにかけてみた例が下記です。

スコアの算出対象となったコミットログのサマリ(Fixes)と、スコア(Hotspots)が算出されているのがお分かりいただけるかと思います。

このように、パターンを何も指定しない場合は「fix」という文字列を含むコミットログが対象になるようです。

$ bugspots .
Scanning . repo
        Found 32 bugfix commits, with 24 hotspots:
        Fixes:
                - fix for PR comments
                - Fix deploy script
               (...中略)
                - Fix: failover when failing to store data into journal retrieve data from journal
        Hotspots:
                0.0011 - Malba-client/src/main/scala/jp/co/shanon/malba/client/MalbaRequestHandler.scala
                0.0011 - Malba-master/src/main/resources/Malba-master.conf
                0.0011 - Malba-master/src/main/resources/application.conf
                0.0011 - Malba-master/src/main/resources/logger.xml
                0.0011 - Malba-master/src/main/scala/jp/co/shanon/malba/worker/Master.scala
                0.0011 - Malba-master/src/main/scala/jp/co/shanon/malba/worker/QueueManager.scala
                0.0006 - Malba-master/src/main/scala/jp/co/shanon/malba/queue/FIFOQueue.scala
                (...中略)
                0.0000 - APIDoc.md

現状の弊社のコミットログはルールがそこまで明確化されておらず、たとえばエンハンスメントも BTS に 入っているので、「bug ではじまる」というルールでエンハンスもヒットしてしまいます。また、bugfix に「fix」と必ず書いているわけでもないので、完全にバグ修正のコミットのみを取り出すのが結構難しかったりします。

このあたりは、今後の運用で改善していく必要がありそうです。ただ、このアルゴリズムは「直近のコミットを重視する」ようになっているので、コミットログの書き方をちょっと見直せば、すぐに効果は出るのではないか、と思っています。

Jenkins に組み込む際の tips

こういったツールは、定期的に実行したほうが効果が大きいので、CI サーバに組み込むのがおすすめです。弊社では Jenkins を主に使っているので、Jenkins に組み込んで実行するようにしています。

その際の注意点が1つだけ。

Jenkins の Git プラグインはデフォルトでは無名のローカルブランチを作りますが、bugspots はブランチを指定しないと動かないので、「Additional Behaviours」->「Check out to specific local branch」にブランチ名(たとえば master)を指定する必要があります。

今後について

実は先ほど Jenkins への組み込みを終えたばかりなので、今後は数値を見ながらどういった活用をしていこうか考え中だったりします。Google ではコードレビューの際に「点数が高いから、気を付けてレビューしよう」みたいな利用をしているそうです。

Github/GHE の pull request にフックして何らかの通知を行えば、似たようなことは簡単にできるのではないか、と思います。あとはファイルごとの「循環複雑度」の合計と掛け算してみたら、リファクタリングすべきファイルの候補の算出とかに使えないかなー、等色々考えています。



0 件のコメント:

コメントを投稿