GitLabで以下を試した時のメモ。
- GitLab PagesでJavadocで生成したhtmlを表示
- GitLabのMerge RequestからJUnitとJaCoCoの結果を表示
なお、これらを実施するにあたり、以下を実行するJobをGitLabのCI/CDパイプライン上に実装した。
- JUnit、JaCoCoの実行
- Javadocの生成
- 生成物のPagesへの引き渡し
今回ベースとしたサンプルコードはこちらで、修正後のコードはこちらとなる。
サンプルコードの作成
JUnitのサンプルを自環境に取り込み、Javadoc確認用コメント、JUnit、JaCoCo向けコードおよび.gitlab-ci.yaml
を作り込んでいく。
このサンプルには最初からテストは実装されているため、JUnitの確認はすぐ出来るようになっている。
@Test
@DisplayName("1 + 1 = 2")
void addsTwoNumbers() {
Calculator calculator = new Calculator();
assertEquals(2, calculator.add(1, 1), "1 + 1 should equal 2");
}
ただし、コメントがないのでJavadocの確認用にコメントを付与する。
package com.example.project;
/**
* Calculatorクラスのコメント
*
* @author hogehoge
*/
public class Calculator {
/**
* addは引数の和を返します
*
* @param a 第一引数
* @param b 第二引数
* @return 第一引数と第二引数の和
*/
public int add(int a, int b) {
return a + b;
}
}
JUnitはbuild.gradle
内でtestで使うよう定義済みである。
test {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed"
}
}
そのため、この時点でJUnitとJavadocはそれぞれ利用可能になっているため、それぞれを動作確認する。
$ ./gradlew test
Starting a Gradle Daemon, 1 incompatible Daemon could not be reused, use --status for details
> Task :test
CalculatorTests > 1 + 1 = 2 PASSED
CalculatorTests > add(int, int, int) > com.example.project.CalculatorTests.add(int, int, int)[1] PASSED
CalculatorTests > add(int, int, int) > com.example.project.CalculatorTests.add(int, int, int)[2] PASSED
CalculatorTests > add(int, int, int) > com.example.project.CalculatorTests.add(int, int, int)[3] PASSED
CalculatorTests > add(int, int, int) > com.example.project.CalculatorTests.add(int, int, int)[4] PASSED
BUILD SUCCESSFUL in 8s
3 actionable tasks: 3 executed
$ ./gradlew javadoc
BUILD SUCCESSFUL in 2s
2 actionable tasks: 1 executed, 1 up-to-date
また、build以下にドキュメントも生成されていることが分かる。
$ find build/ |grep /index.html
build/docs/javadoc/index.html
build/reports/tests/test/index.html
次に、JaCoCoも実行できるようにする。JaCoCoは標準では動かないので、build.gradle
に以下を追記する。
細かい設定をしたい人はこちらを参照するとよい。
plugins {
id 'jacoco'
}
jacocoTestReport {
reports {
xml.required = true
csv.required = false
html.required = false
}
dependsOn test
}
test {
finalizedBy jacocoTestReport
}
動作確認する。
$ ./gradlew test
> Task :test
CalculatorTests > 1 + 1 = 2 PASSED
CalculatorTests > add(int, int, int) > com.example.project.CalculatorTests.add(int, int, int)[1] PASSED
CalculatorTests > add(int, int, int) > com.example.project.CalculatorTests.add(int, int, int)[2] PASSED
CalculatorTests > add(int, int, int) > com.example.project.CalculatorTests.add(int, int, int)[3] PASSED
CalculatorTests > add(int, int, int) > com.example.project.CalculatorTests.add(int, int, int)[4] PASSED
BUILD SUCCESSFUL in 4s
4 actionable tasks: 4 executed
レポートはbuild/reports/jacoco/test/jacocoTestReport.xml
に出力される。
.gitlab-ci.yml
の作成
GitLab PagesとMerge Requestに表示させるために、以下のジョブを含む.gitlab-ci.yml
を作成する。
-
make-javadoc
:Javadoc生成 -
unit-test
:JUnitとJaCoCoのレポート生成 -
convert-to-cobertura
:JaCoCoレポートをCobertura形式に変換 -
pages
:GitLab Pagesで表示
ポイントとしては以下となる。
- UnitTest、Coverageの結果をGitLabのArtifactに指定すると、Merge Requestで表示されるようになる(Test coverage visualization)。
- JaCoCoのレポートがGitLabで直接扱えないため、Cobertura形式に変換する(変換にはこちらを使う)
JaCoCoのレポートが直接使えない問題はGitLabのこちらのIssueで議論されている。近い将来サポートされるようなことが書いているので、興味がある人はwatchしておくとよい。
それぞれのJobの依存関係は以下。
Javadoc生成用Job
Javadoc生成のJobは以下となる。
make-javadoc:
stage: unit-test
rules:
- if: $CI_PIPELINE_SOURCE == "push"
image: gradle:7.5.0-jdk17
script:
- |
./gradlew javadoc
cp -r build/docs/javadoc/ public/
artifacts:
paths:
- public/
Pagesに生成したドキュメントをartifactsで渡す前にpublicディレクトリを作成している。
これはGitLab Pagesがpublic以下にあるhtmlを見に行くため、こちらでpublicに整形している。
なお、public以外のディレクトリは使えない模様。
JUnitとJaCoCoのレポート生成用Job
JUnitとJaCoCoのレポート生成のJobは以下となる。
unit-test:
stage: unit-test
rules:
- if: $CI_PIPELINE_SOURCE == "push"
image: gradle:7.5.0-jdk17
allow_failure: true
script:
- |
./gradlew test
artifacts:
reports:
junit: build/test-results/**/TEST-*.xml
paths:
- build/reports/jacoco/test/jacocoTestReport.xml
artifacts.reports.junit
でJUnitの結果を渡している。
なお、GitLabのドキュメントの書き方だとファイルを見つけてくれなかったので、オフィシャルのものから少しパスの表現を変えている。
また、合わせてJaCoCoの結果もartifactsに渡しているが、これはGitLab向けではなく後続のJobに渡すためである。
JaCoCoレポートをCobertura形式に変換するJob
JaCoCoレポートをCobertura形式に変換するJobは以下となる。
needs:
- job: unit-test
artifacts: true
stage: unit-test
image: haynes/jacoco2cobertura:1.0.7
script:
- python /opt/cover2cover.py build/reports/jacoco/test/jacocoTestReport.xml $CI_PROJECT_DIR/src/main/java/ > build/reports/coverage.xml
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: build/reports/coverage.xml
needs
で前提Jobを定義し、artifacts:true
を設定することでJaCoCoの結果を受け取れるようにしている。
コンテナイメージやスクリプトはこちらを参考にした。
GitLab Pagesで表示するJob
Pagesで表示するためのJobは以下となる。
pages:
needs:
- job: make-javadoc
artifacts: true
rules:
- if: $CI_PIPELINE_SOURCE == "push"
image: busybox
stage: pages
script:
- echo "The site will be deployed to $CI_PAGES_URL"
artifacts:
paths:
- public/
やることは特になく、Javadoc作成したpublicディレクトリをそのまま渡している。また、こちらもneeds
でmake-javadocとの依存関係を記載した。
最終的な.gitlab-ci.yml
はこちらとなる。
動作確認
適当なMerge Requestを作成し、以下の修正を入れてコミットした。
public int add(int a, int b) {
return a + b;
}
-
+ public int sub(int a, int b) {
+ return a - b;
+ }
}
パイプラインの全てのJobが完了した後、それぞれどうなったか見ていく。
まず、該当するMerge requestのChangesを見ると、緑と赤の線が表示されるようになる。緑の線はカバー出来ており、赤の線はカバー出来ていない箇所となる。
今回新規に追加したメソッドに対応するテストは書かなかったため、カバーされていないことがこれで分かる。
次にJUnitの結果についても確認する。
先程実行したパイプラインを開くと、"Tests 5"というタブが増えていることが分かる。
クリックすると、テストの件数やどのテストで失敗したかなどが分かる。
最後にJavadocの内容をGitLab Pagesから確認する。
GitLab PagesのURLはhttps://<Group名>.pages.<gitlabのドメイン>/<Project名>
となっており、サイドバーのSettings->Pagesから辿ることが出来る。
また環境変数CI_PAGES_URL
の中にも入っているため、パイプライン上で表示させれば、Jobの確認のついでに参照することもできる。