Nikkei Advent Calendar 2020の15日目の記事です。
はじめに
日経IDチームで認証基盤の開発を担当している野口です。
日経IDチームでは以下のような技術スタックで開発をしています。
- 開発言語: Kotlin
- コード管理: GitHub
- CI/CD: CircleCI
- インフラ: AWS
CircleCIではbranchへのpushをトリガーとして単体テストを実行し、テスト結果およびカバレッジのデータをビルドアーティファクトに保存しています。そのアーティファクトをチームメンバーが見られるようにし、テストの品質の向上に努めています。
その中で「テスト結果を見やすくしたい」という声があり、競合サービスなどを調査していたところ、AWS CodeBuildのテストレポートの機能を発見しました。
日経IDチームではKotlinに対応している以下のテストフレームワーク・ライブラリを採用しています。
- テストフレームワーク: JUnit
- カバレッジ測定ライブラリ: JaCoCo
CodeBuildのテストレポートは、JUnitやJaCoCoに対応しているということだったので、実際に試してみようと思います。
今回は試したのは以下の二つです。
- JUnitによるテストレポートの作成
- JaCoCoによるコードカバレッジレポートの作成
準備
メインのコードとテストコードを書いていきます。
class Calculator {
fun add(a: Int, b: Int): Int {
return a + b
}
}
テストコード
package com.example.project
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
class AddTests {
@Test
fun `1 + 1 = 2`() {
val calculator = Calculator()
assertEquals(2, calculator.add(1, 1), "1 + 1 should equal 2")
}
@Test
fun `2 + 3 = 5`() {
val calculator = Calculator()
assertEquals(5, calculator.add(2, 3), "2 + 3 should equal 5")
}
@Test
fun `1 + 99 = 100`() {
val calculator = Calculator()
assertEquals(100, calculator.add(1, 99), "1 + 99 should equal 100")
}
}
テストレポートの作成
公式ドキュメント ビルドプロジェクトの作成(コンソール)を参考にビルドプロジェクトを作成します。
今回は buildspec.yml
に commands
と reports
の設定を書きます。
version: 0.2
phases:
build:
commands:
- ./gradlew test
reports:
junit:
files:
- '**/*'
base-directory: "build/test-results"
file-format: 'JUnitXML'
reports
のパラメータはドキュメントをご参照ください。
上記の buildspec.yml
をrootディレクトに配置し、ビルドを実行します。
保存されたレポートは以下のようになります。

今回は3つのテストケースが実行され、3つとも成功していることが可視化されています。
buildspec.yml
にたった6行追加しただけでレポート作成をすることができました。
コードカバレッジレポートの作成
次にコードカバレッジレポートを作成します。
コードカバレッジの機能は、テストレポートがGAされた2020年5月にはなかった機能で、2020年7月より利用可能になりました(記事)。
日経IDチームの開発ではJaCoCoを使用しており、CodeBuildもJaCoCo XMLに対応しているとのことですので、今回は JaCoCo XMLのコードカバレッジレポートを作成します。
Gradle公式ドキュメント を参考にJaCoCoに必要な設定をした後、 buildspec.yml
を更新します。
version: 0.2
phases:
build:
commands:
- ./gradlew test
- ./gradlew jacocoTestReport
reports:
junit:
files:
- '**/*'
base-directory: "build/test-results"
file-format: 'JUnitXML'
jacoco:
files:
- 'build/reports/jacoco/report.xml'
file-format: 'JACOCOXML'
条件分岐があるコードを作ってみます。
fun isEven(num: Int): Boolean {
if (num % 2 == 0) {
return true
}
return false
}
ここでは意図的に一部のライン・ブランチを通らないテストを書いてみます。
package com.example.project
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
class IsEvenTests {
@Test
fun `2 is even`() {
val calculator = Calculator()
assertEquals(true, calculator.isEven(2), "2 should be even")
}
}
CodeBuildを実行すると、タイプがコードカバレッジのレポートが生成されています。以下はコードカバレッジレポートの概要になります。
ラインの20%、ブランチの50%がカバーされていないことが分かります。

そこですべてのライン・ブランチをカバーするように以下のテストケースを追加します。
class IsEvenTests {
@Test
fun `2 is even`() {
val calculator = Calculator()
assertEquals(true, calculator.isEven(2), "2 should be even")
}
@Test
fun `3 is not even`() {
val calculator = Calculator()
assertEquals(false, calculator.isEven(3), "3 should not be even")
}
}

すべてのライン・ブランチを通ることが確認できましたね。
テストレポート作成と同様、reports
に数行追加するだけで簡単にコードカバレッジレポートを作成し、結果を可視化することができました。
所感
buildspec.yml
に数行追加するだけでCodeBuildのテストレポート機能が使えました。CircleCIにもアーティファクトを保存する機能はありますが、テスト結果を可視化・数値化してくれる機能はないので、CodeBuildのテストレポートは魅力的な機能だと思いました。
一方、気になる点が2つありました。
- ** レポートあたりのテストケースの最大数が500 **
執筆している時点(2020年12月)のAWS CodeBuildのクォータによると、レポートあたりのテストケースの最大数は500件とのことでした。
日経IDチームが開発しているプロジェクトではひとつのレポジトリ内にテストケースが500以上あります。最大値を超えた場合は超過分のテストケースはCodeBuildのテストレポートから確認することができないようです。
- ** どのライン・ブランチがカバーされているのかがわからない **
何%カバーされているかは分かりますが、どのライン・ブランチがカバーされていないかがCodeBuildのテストレポートでは確認できませんでした。
JaCoCoはxml以外にもhtml, csv形式に対応しています。日経IDチームではhtmlのレポートをCircleCIのartifactsに保存し、どのライン・ブランチがカバーされていないか確認するようにしています。 ビルド結果をS3へ出力し、静的ウェブサイトでホスティングすることで実現できそうですが(ドキュメント)、CodeBuild内で完結することはできないようです。
おわりに
CodeBuildのテストレポートは2020年5月にGAされた新しい機能なので、今後のアップデートに期待したいと思います。 テスト結果の数値化・可視化ができるとレビューする際のチーム共通の指標となるので、今後も関連する技術やサービスを調査していこうと思います。
明日は「Terraform + GitHub + CircleCIで行うAWSマルチアカウント環境のテンプレート設定」です。お楽しみに!