kcovを使ってRustプログラムのカバレッジを測定する
本記事は Rust Advent Calendar 2015 13日目の記事です。
前置き
Rust 1.5リリースおめでとうございます!!!
cargo install
の登場により、Rust製ツール群のインストールが飛躍的に楽になりました。最近のアップデートに追従できていなかったという方も、是非是非ダウンロードしてみてください。
背景
Rustには、 言語組み込みのユニットテスト機能 や、cargo test
のインテグレーションテストサポートなど、テストを実行させる方法は充実しているのですが、gcov相当のカバレッジ採取機能については、 2015年12月時点では残念ながらサポートされていません (RFCリポジトリにIssueはあります)。しかし、Rust にはプログラムのDWARF情報 (デバッグ情報) を生成する機能があるため、 kcov というプログラムを利用することでカバレッジを採取することが可能です。
本記事では、 kcov を利用して Rust プログラムのカバレッジを測定する方法について説明します。
kcov のインストール
各ディストリビューションでバイナリが配付されていない場合、ソースコードからビルドすることになります。 以下に載っているコマンドラインを参考にしてみてください。
- Ubuntuの場合
- CentOSの場合
Arch Linux の場合: AUR に kcov-git パッケージが存在するため、以下コマンドでインストール可能です (yaourt を利用している場合)。
$ yaourt -S kcov-git
kcov を使う
cargo test --no-run
でデバッグシンボルのついたテスト用実行ファイルを作成し、kcov 経由で実行します。
$ cargo test --no-run $ kcov target/cov target/debug/$TEST_EXECUTABLE
上記実行すると、 target/cov
ディレクトリ配下にカバレッジ測定結果を格納したHTMLファイルが生成されます。
デフォルトでは、 ~/.cargo
配下のファイル (Cargo.toml
で依存関係として指定したライブラリ) についてもカバレッジ測定対象となってしまうため、邪魔であれば以下のように --exclude-pattern
オプションを指定することで、カバレッジ測定対象を絞ることが出来ます。
$ kcov --exclude-pattern=/.cargo target/cov target/debug/$TEST_EXECUTABLE # multirust を使っている場合、以下 $ kcov --exclude-pattern=/.multirust target/cov target/debug/$TEST_EXECUTABLE
また、kcov
を複数回実行した場合、カバレッジ情報が蓄積されていきます。引数などの条件を変えて何度もコマンドを実行し、それらの結果を合算することなどが可能です。
$ kcov --exclude-pattern=/.cargo target/cov target/debug/$TEST_EXECUTABLE $ kcov --exclude-pattern=/.cargo target/cov target/debug/$TEST_EXECUTABLE --ignored
Coveralls との連携
Coveralls とは、 GitHub (BitBucketも?) で開発しているソースコードのテストカバレッジを表示してくれるサービスです。 Travis CI と連携して利用します。
kcov には測定したカバレッジを Coveralls へと送信してくれる機能があり、.travis.yml
上で kcov を以下のように呼び出すよう設定するだけで Coveralls を利用できます。
$ kcov --coveralls-id=${TRAVIS_JOB_ID} target/cov target/debug/$TEST_EXECUTABLE
ただし、Travis CI にはデフォルトで kcov はインストールされていないため、 .travis.yml
中で kcov をインストールしてやる必要があります。
language: rust sudo: false addons: apt: packages: - libcurl4-openssl-dev - libelf-dev - libdw-dev before_script: - | if [ "${TRAVIS_OS_NAME}" = "linux" ]; then export KCOV="${TRAVIS_BUILD_DIR}/kcov/build/src/kcov --exclude-pattern=/.cargo --coveralls-id=${TRAVIS_JOB_ID} ${TRAVIS_BUILD_DIR}/coverage" wget https://github.com/SimonKagstrom/kcov/archive/master.zip unzip master.zip mv kcov-master kcov mkdir kcov/build cd kcov/build cmake .. make cd ${TRAVIS_BUILD_DIR} fi script: - ${KCOV} target/debug/$TEST_EXECUTABLE
すこしめんどくさいですね。
travis-cargo を使う
すべての Rust プロジェクトの .travis.yml
に kcov のインストール手順を書くのは面倒だというあなたのために、 travis-cargo という便利ツールが公開されています。
rustdoc
の生成物を github.io
にアップロードするなど、カバレッジ生成採取の便利な機能も搭載されています。
一部、travis-cargo
では実現できないこともあるのですが (cargo test
で生成されるバイナリ以外のカバレッジ採取する場合など)、多くの場合、 travis-cargo
を使うのが便利だと思います。
最後に
筆者が公開している以下リポジトリでは、ビルド時にカバレッジを採取し、バッジとして README に表示しています。.travis.yml
の書き方の参考にどうぞ。
- gifnksm/srither: Rustで書かれたスリザーリンク (パズル) のソルバー。
travis-cargo
は使っていません。 - gifnksm/oauth-client-rs
- gifnksm/generic-matrix-rs
- gifnksm/union-find-rs
- gifnksm/twitter-api-rs
- gifnksm/topological-sort-rs
- gifnksm/ProjectEulerRust
- gifnksm/polynomial-rs