TL; DR
結論から言えば、オススメです。
下記のような画面を見て、問題なさそうだと思った方は、是非とも使ってみてください。

現在では、未実行ラインを表示/確認ができません。
しかし、実装される未来は近い気がします。
AWS様ありがとうございます、一生ついていきます!
ですが、あともう一声、お願いします!!!
はじめに
2020年5月22日になり、テストレポート機能が一般公開されました。
それから早2ヶ月後の7月30日、ついに欲しかったコードカバレッジレポートのサポートがされました。
AWS CodeBuild がコードカバレッジレポートをサポート
この機能がどのようなものなのか、実際に動かして確かめてみたくありませんか?
ということで、実際に試してみます。
なお、本記事は下記の続きとして記載しています。
よろしければ、下記もご覧ください。
CodeBuildのテストレポート機能が一般公開されたから使ってケチつけてみた - Qiita
事前準備
コードカバレッジレポートってなんやねん、という方は、ざっと流し読みしてみてください。
コードカバレッジレポート
ここでいうコードカバレッジレポートは、テスト実行時のソースコードカバレッジ(網羅率)を集計したファイルのことです。
カバレッジ(網羅率)分析とは | ソフトウェアの検証の種類 | テクマトリックス株式会社
JaCoCoが有名ですが、それ以外にも多くのフォーマットがあるみたいです。
CodeBuildのレポート機能では、上記コードカバレッジレポートファイルを組込むことで、カバレッジを可視化できます。
似たようなサービスとして、 Codecov や Coveralls が挙げられますね。
実際に試してみた
CodeBuildで、テストレポート機能におけるコードカバレッジレポートの表示動作確認をしてみましょう。
なお、CodeCommitとCodeBuildのプロジェクトの新規作成については、 以前の記事で記載 しているため、省略します。
CodeCommitにソースコードをプッシュする
CodeCommitに、CodeBuildでビルドするためのソースコードをプッシュします。
動作確認ができればなんでも良いので、好きな言語で試してみましょう。
つまり僕は、前回同様Perlで試してみるわけです。
ディレクトリ構造は、下記の通りです。
test-reports-sample/
|- buildspec.yml # CodeBuildの実行ファイル
|- lib/
| |- sample.pm # テスト対象コード(モジュール)
|
|- t/
|- sample.t # テストコード
まず、テスト対象コードです。
use strict;
use warnings;
use utf8;
package Sample;
sub get_one {
my ($self, $is_true) = @_;
print "True¥n" if $is_true;
return 1;
}
sub get_two {
return 2;
}
1;
このうち、ブランチカバレッジの表示用に書いている箇所は print "True¥n" if $is_true;
の部分です。
$is_true
は引数に応じて変化します。
引数が真の場合 (Perlなので 1
などを引数に設定した場合)、 print "True¥n"
が実行されます。
次に、テストコードです。
use strict;
use warnings;
use utf8;
use Test::More;
use lib 'lib';
use sample;
subtest 'サンプルテスト' => sub {
my $test = "pass";
ok $test;
};
subtest 'サンプルテスト2' => sub {
my $expected = 1;
my $actual = Sample->get_one;
is $actual, $expected;
};
done_testing;
サンプルテスト
については、以前のコードと同じため、説明は省略します。
use lib 'lib';
にて lib/
ディレクトリにパスを通し、 use sample
で lib/sample.pm
モジュールをインポートします。
また、 サンプルテスト2
における Sample->get_one
により、 lib/sample.pm
モジュールにおける get_one
関数を実行します。
下記2点がポイントです。
-
get_two
関数を呼出していない -
if $is_true
は真になり得ず、ブランチカバレッジは100%にならない
CodeBuildでは、buildspec.ymlファイルにより動作を定義できるため、こちらも作ります。
version: 0.2
phases:
install:
commands:
- curl -L https://cpanmin.us/ -o cpanm && mv cpanm /usr/bin/cpanm && chmod +x /usr/bin/cpanm
- curl -fsSL --compressed https://git.io/cpm > cpm && mv cpm /usr/bin/cpm && chmod +x /usr/bin/cpm
build:
commands:
- cpm install -g TAP::Harness::JUnit
- cpm install -g Devel::Cover::Report::Clover
# - prove -lv -j5 --harness TAP::Harness::JUnit sample.t # テストレポートだけを出力する場合のコマンド
- HARNESS_PERL_SWITCHES="-MDevel::Cover=+ignore,^t" prove -lvr -j5 --harness TAP::Harness::JUnit t
- cover -report clover
reports:
sample-test-report:
files:
- junit_output.xml
sample-coverage-clover-report:
file-format: CloverXml
files:
- cover_db/clover.xml
Devel::Cover::Report::Clover
モジュールをインストールすることで、Clover形式のXMLを出力できます。
HARNESS_PERL_SWITCHES="-MDevel::Cover=+ignore,^t" prove -lvr -j5 --harness TAP::Harness::JUnit t
コマンドにて、 junit_output.xml
テストレポートファイルを生成し、同時にテストカバレッジを計測するため cover_db
ディレクトリを生成します。
その後 cover -report clover
コマンドにて、Clover形式のXMLである cover_db/clover.xml
ファイルを生成します。
上記 cover_db/clover.xml
ファイルを、 reports
における sample-coverage-clover-report
にて、 CloverXml
フォーマットを指定して設定します。
以降、前回との差分とPerl固有の内容についての詳細です。
前回のCodeBuildイメージは Amazon Linux だったためか、なぜか依存モジュールをインストールしてくれなくて大変な思いをしました。 今回は Ubuntu イメージにしたことで、 `expat-devel` のDebian版ライブラリ `libexpat1-dev` をインストールする必要がなくなり、必要なPerlモジュールだけをインストールするだけで依存モジュールのインストールもしてくれました。
また、 `Devel::Cover` モジュールの `cover` コマンドには、JSON形式のコードカバレッジレポートファイルを生成してくれます。 しかし、CodeBuildのテストレポート機能で対応しているSimpleCov JSON形式とは異なるため、正常に読み込んでくれません。 `Devel::Cover::Report::Clover` 以外であっても、CodeBuildのテストレポート機能が対応している形式で出力してあげれば、正常に読み込んでくれると思います。
- CodeBuildに関するもの
- Perlに関するもの
- cover - report coverage statistics - metacpan.org
- Devel::Cover - Code coverage metrics for Perl - metacpan.org
- Devel::Cover::Report::Clover - Backend for Clover reporting of coverage statistics - metacpan.org
- 第49回 CPANモジュールの品質を支えるCI技術(3):Perl Hackers Hub|gihyo.jp … 技術評論社
- lib - モジュールの検索パスを追加 - Perlゼミ
- perl - How to install XML::Parser without expat-devel? - Stack Overflow
CodeBuildで自動テストする
上記3ファイルを入れたリポジトリで、CodeCommit経由でCodeBuildを走らせます。
CodeBuildによるビルドは、手動で構いません。
CodeBuildでビルド通過後にテストレポートを確認する
CodeBuildでビルドが完了したら、テストレポートを確認しましょう。
CodeBuildにtest-reports-sampleビルドプロジェクトを作成し、ビルド結果のレポートタブを開きます。

以前までの画面とは異なり、「タイプ」という項目が追加されています。
また、タイプの中身として「テスト」と「コードカバレッジ」の2種類が存在することがわかります。
では、コードカバレッジである test-report-sample-sample-coverage-clover-report
グループのレポートを見てみましょう。

カバレッジ測定結果として、ラインカバレッジとブランチカバレッジの円グラフがデカデカと載っていることがわかります。
また、 lib/sample.pm
ファイルを計測していることが、一覧で表示されていることがわかります。
レポートグループ画面は、下記の通り(再掲)です。
カバレッジの履歴が一眼でわかります。
平均の数値はよくわかりませんが、 こっちは便利そうですね。

ただ、ここでわかりづらいのですが、ラインカバレッジとブランチカバレッジは独立している、という点です。
それぞれについて、説明します。
ラインカバレッジとブランチカバレッジの解説
以降は、Perlにおける Devel::Cover
モジュール固有の問題である可能性もあるので、話半分で聞いてください。
ラインカバレッジの項目では、1行だけ実行されなかったことがわかります。
ここでいう未実行の1行とは、 get_two
関数における return 2;
の行のことを指します。
その証拠に、 get_two
関数を呼出すテストコードを追記した場合、下記のような画面になります。
subtest 'サンプルテスト3' => sub {
my $expected = 2;
my $actual = Sample->get_two;
is $actual, $expected;
};
ラインカバレッジ0って何......?

つまり、 print "True¥n" if $is_true;
の行における print "True¥n"
は実行されていないにも関わらず、行単位では実行しているためにラインカバレッジは100%になった、というわけです1。
一方、ブランチカバレッジは2つしかありませんが、そのうち1つは print "True¥n" if $is_true;
の $is_true
が 真である場合の実行分岐を指しています。
その証拠に、 $is_true
が真になる get_one
関数を呼出すテストコードを追記した場合、下記のような画面になります。
サンプルテスト3は、スキップして実行します。
subtest 'サンプルテスト3' => sub {
plan(skip_all => 'ignore test'); # サンプルテスト3はスキップする
my $expected = 2;
my $actual = Sample->get_two;
is $actual, $expected;
};
subtest 'サンプルテスト4' => sub {
my $expected = 1;
my $actual = Sample->get_one(1);
is $actual, $expected;
};
ブランチカバレッジ0って何......?

ここで注意すべき点としては、ブランチカバレッジはラインカバレッジの上位互換ではない、という点です。
$ C0 \leqq C1 $ という不等式が成立しない点に注意してください。
ちなみに、全てのカバレッジを100%にすると、下記のような表示画面になります。

CodeBuildテストレポート機能の利点/欠点
機能自体は理解できたので、CodeBuildテストレポート機能におけるコードカバレッジレポートの利点と欠点を、それぞれ書いていきます。
利点
前回と被る面もありますが、利点を挙げていきます。
グラフィカルなUIでテスト結果が確認できる
以前までは、CodeBuildのテスト結果は全てCloudWatch LogsのCUIライクな表示でしか確認できませんでした。
テストレポートだけでなくコードカバレッジレポートもグラフィカルに表示できることで、テストレポートの必要最低限の機能は満たせたのではないかと考えます。
折れ線グラフがわかりやすい
僕の書いた記事を、AWSの中の人が読んでくださったのか定かではありませんが、折れ線グラフが非常にわかりやすいです。
折れ線グラフであれば直近のカバレッジが見えますし、どれだけカバレッジを増やしているかも一目瞭然です。
別サービスを契約しなくて良い
現在の機能だけでも、CodecovやCoverallsなどの別サービスを契約する必要性は下がります。
CodeCommitを使う際はプライベートリポジトリの場合が多いため、プライベートリポジトリの場合は有料契約になってしまう上記サービスを使わなくても良い点は、利点としてかなり大きいと思います。
欠点
いくつか気になる点はあるので、~~(また、タイトルでもケチつけると書いちゃったので、)~~粗探しをします。
ただ、前回よりはずいぶんよくなったと思います。
平均ラインカバレッジ率/平均ブランチカバレッジ率の意味がわからない
直前以外の平均ラインカバレッジ/平均ブランチカバレッジも、あまり使わない気がします。
大事なのは、直前のカバレッジだと思うのですが、なぜ平均値を出しているのか、よくわかりません。
しかも、1度でもテストで失敗してしまうと(理論上)100%には二度と戻らないのも、悲しいです。
単純に、最新カバレッジを表示するのではダメなのでしょうか?
あと、ちょっとしたことですが、カバレッジ率を日本語に訳すと網羅率率ですか???
平均ラインカバレッジ/平均ブランチカバレッジが100%の時の表示が気になる
せっかく頑張って100%にしたのに、 0
は悲しいです。
ここは 100%
にしてほしいなーと思います。
レポートグループタイプが固定
一度レポートグループを作成してしまうと、作成したレポートグループのタイプを変更できません。
レポートグループタイプおよびレポートタイプは、 TEST
と CODE_COVERAGE
の2種類があります。
レポートタイプは、 buildspec.yml
で指定した file-format
で、下記に依存して自動的に設定されます。
The following test report file formats are supported:
- CucumberJson
- JunitXml
- NunitXml
- TestNGXml
- VisualStudioTrx
The following code coverage report formats are supported:
- JaCoCoXml
- SimpleCov
- CloverXml
- CoberturaXml
前者が TEST
、後者が CODE_COVERAGE
として、内部処理で分けているみたいです。
また、レポートグループタイプは、最初に buildspec.yml
でレポートを自動生成する際に設定した file-format
の値に依存したタイプが、これまた自動的に設定されます。
レポートグループタイプは(AWSマネジメントコンソール上でも)変更できないため、レポートグループを削除する or レポートグループ名を変更する、いずれかをしない限り、次のようなエラーが発生し、CodeBuildがエラー終了します。
CLIENT_ERROR: Error in UPLOAD_ARTIFACTS phase:
[CoverageReports: [error creating report: InvalidInputException: Report group type doesn't match expected report type, report group type is TEST, but report type is CODE_COVERAGE]]翻訳結果:
CLIENT_ERROR:UPLOAD_ARTIFACTSフェーズのエラー:
[CoverageReports: [レポートの作成エラー: InvalidInputException: レポートグループタイプが予期されるレポートタイプと一致しません。レポートグループタイプはTESTですが、レポートタイプはCODE_COVERAGEです]]
つまり、最初に file-format
を間違えて設定してしまうと、以降はCodeBuildのフェーズエラーを見ない限りエラー内容に気付けません。
最初に使おうと試行錯誤している利用者には、思わぬ落とし穴になりそうです。
すみませんが、この問題の解決策はすぐには思いつきそうにありません。
今後のアップデートに期待します。
おわりに
タイトルでは貶しているように見えたらごめんなさい。
中身としては、結構ベタ褒めで書いたつもりです。
それだけ、僕はこの機能を求めていました。
AWSの中の人、本当にお疲れ様です!
今後もアップデートがあると信じて、期待しましょう!!!
-
ラインカバレッジの定義としては、別に間違っていません。これに気をつけるために、ブランチカバレッジという物があるわけです。 ↩