2017年の春に、Atlassian Cloverというカバレッジを取得するツールがOSSになりました。
Atlassian Clover がオープンソースに | Atlassian Blogs
OpenClover - Java, Groovy and AspectJ code coverage tool
ということで、ちょっと試してみようかと。
参考ドキュメント
参考ドキュメントとしては、このあたりを。
OpenClover 4.2 : Clover-for-Maven Quick Start Guide
OpenClover 4.2 : Clover-for-Maven tutorials
OpenClover 4.2 : Clover-for-Maven User's Guide
Clover Maven Plugin – Maven 2 Clover Plugin Introduction
チュートリアルは、Bitbucketへのリンクとなっています。
clover-maven-pluginのsrc/itにサンプルがあるということなので
openclover / clover-maven-plugin / source / src / it — Bitbucket
単純なプロジェクト構成と
openclover / clover-maven-plugin / source / src / it / simple — Bitbucket
マルチプロジェクト構成とかを見ておくとよいかもしれません。
openclover / clover-maven-plugin / source / src / it / multiproject — Bitbucket
とりあえずサンプルコード
まずは、サンプルコードを書いてみます。
最初は、OpenCloverの設定抜きで。
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.0.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>3.8.0</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.19</version> <dependencies> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-surefire-provider</artifactId> <version>1.0.1</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.0.1</version> </dependency> </dependencies> </plugin> </plugins> </build>
テスト対象コード。
src/main/java/org/littlewings/example/CalcService.java
package org.littlewings.example; public class CalcService { public int add(int a, int b) { return a + b; } public int minus(int a, int b) { return a - b; } public int multiply(int a, int b) { return a * b; } }
テストコード。
src/test/java/org/littlewings/example/CalcServiceTest.java
package org.littlewings.example; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; class CalcServiceTest { @Test public void add() { CalcService calcService = new CalcService(); assertThat(calcService.add(1, 2)).isEqualTo(3); } @Test public void multiply() { CalcService calcService = new CalcService(); assertThat(calcService.multiply(2, 3)).isEqualTo(6); } }
minusへのテストがありません。
OpenCloverの設定をする
では、ここからOpenCloverの設定をpom.xmlに加えてみます。
参考にするドキュメントは、こちらがよい気がします。
プラグインに、OpenCloverのMaven Pluginを加えます。
<plugin> <groupId>org.openclover</groupId> <artifactId>clover-maven-plugin</artifactId> <version>4.2.0</version> </plugin>
siteゴール用に、reporting設定も加えておいてもよいでしょう。
<reporting> <plugins> <plugin> <groupId>org.openclover</groupId> <artifactId>clover-maven-plugin</artifactId> </plugin> </plugins> </reporting>
この状態で、ドキュメントに倣って
$ mvn clean clover:setup test clover:aggregate clover:clover
と実行すると「target/site/clover」ディレクトリに、レポートができています。
$ ls -l target/site/clover/index.html -rw-rw-r-- 1 xxxxx xxxxx 412 11月 4 21:26 target/site/clover/index.html
「Code coverage」が66.7%なのは、テストしていないメソッドがあるからですね。
もしくは、「clover:setup」の部分を「clover:instrument」にしてもOKです。
$ mvn clean clover:instrument test clover:aggregate clover:clover
作成されるレポートは、省略します。
「clover:setup」と「clover:instrument」の違いは、次のとおりです。
The clover:setup goal performs instrumentation in the main build life cycle, therefore it's not recommended to use it together with 'install' or 'deploy' goals (unless this is your intention). The benefit of this approach is that build is made only once. Furthermore, clover:setup supports instrumentation of Groovy code (while clover:instrument does not).
The clover:instrument goal can be used if you need to actually install or deploy non-instrumented project's artifact and have Clover run at the same time. This will fork a custom build life cycle and run it till the "verify" phase and cause each Clover artifact to contain the -clover classifier. A drawback of this approach is that the build and tests are performed twice.
http://openclover.org/doc/manual/4.2.0/maven--basic-usage.html#Basicusage-Usingclover:setupvsclover:instrumentvsclover:instrument-test
「clover:setup」だと、メインのビルドライフサイクルに組み込まれてしまうので、「install」や「deploy」のゴールと一緒に使うのは
お勧めされません。
これは、「clover:setup」の後の「target/classes」ディレクトリを見るとわかります。
$ ls -l target/classes/org/littlewings/example 合計 12 -rw-rw-r-- 1 xxxxx xxxxx 1713 11月 4 21:33 CalcService$__CLR4_2_000j9lb8369$1.class -rw-rw-r-- 1 xxxxx xxxxx 3840 11月 4 21:33 CalcService$__CLR4_2_000j9lb8369.class -rw-rw-r-- 1 xxxxx xxxxx 1339 11月 4 21:33 CalcService.class
OpenCloverによって拡張されたクラスファイルが生成されています。
「clover:instrument」の場合だと、「target/classes」配下は通常通りで、「target/clover/classes」配下に先ほどの「clover:setup」で
生成されていたようなファイルが出力されています。
$ ls -l target/classes/org/littlewings/example 合計 4 -rw-rw-r-- 1 xxxxx xxxxx 591 11月 4 21:35 CalcService.class $ ls -l target/clover/classes/org/littlewings/example 合計 12 -rw-rw-r-- 1 xxxxx xxxxx 1713 11月 4 21:35 CalcService$__CLR4_2_000j9lbafwn$1.class -rw-rw-r-- 1 xxxxx xxxxx 3840 11月 4 21:35 CalcService$__CLR4_2_000j9lbafwn.class -rw-rw-r-- 1 xxxxx xxxxx 1339 11月 4 21:35 CalcService.class
「clover:instrument」を使用すると、プロダクションコードとOpenClover込みのコードを分離できますが、代わりとして
テストが2回実行されます。
通常、「verify」などと合わせて使い、「-clover」サフィックスのアーティファクト(classfier)が生成されるので、
こちらを使用するようです。
補足)
「-clover」サフィックスのアーティファクトが生成される場合は、「target/clover」ディレクトリ配下に生成されることになります。
$ ls -l target/clover/openclover-simple-0.0.1-SNAPSHOT-clover.jar -rw-rw-r-- 1 xxxxx xxxxx 6872 11月 4 21:48 target/clover/openclover-simple-0.0.1-SNAPSHOT-clover.jar
OpenCloverのMaven Pluginのサンプルなどが、instrumentを使いつつverifyを想定したサンプルを書いているのは、
このあたりが理由かなと思います。
openclover / clover-maven-plugin / source / src / it / simple / pom.xml — Bitbucket
ちなみに、他の「clover:aggregate」と「clover:clover」の意味ですが、aggregateはMavenマルチモジュールの場合に各モジュールの
カバレッジを集約するために使い、cloverでレポートが生成されます。
つまり、今回のサンプルではaggregateは意味がありません…。
外しても、問題なくレポートが生成されます。
$ mvn clean clover:setup test clover:clover
「mvn test」でカバレッジレポートを生成したい場合
「mvn test」くらいで、ここまでの処理を実行したい場合は、次のように書くとよいでしょう。
<plugin> <groupId>org.openclover</groupId> <artifactId>clover-maven-plugin</artifactId> <version>4.2.0</version> <executions> <execution> <id>clover-instrument</id> <phase>generate-sources</phase> <goals> <!-- <goal>setup</goal> --> <goal>instrument</goal> </goals> </execution> <execution> <id>clover-test</id> <phase>test</phase> <goals> <goal>aggregate</goal> <goal>clover</goal> </goals> </execution> </executions> </plugin>
「setup」か「instrument」は、用途に応じて選ぶ感じで。
「mvn verify」時に動作するように設定する
こちらのサンプルを参考にするとよいでしょう。
openclover / clover-maven-plugin / source / src / it / simple / pom.xml — Bitbucket
ただ、このサンプルのままだと「clover:clover」がないのでレポートが生成されません。つける場合は、こんな感じで。
<plugin> <groupId>org.openclover</groupId> <artifactId>clover-maven-plugin</artifactId> <version>4.2.0</version> <executions> <execution> <id>main</id> <phase>verify</phase> <goals> <goal>instrument</goal> <goal>check</goal> <goal>clover</goal> </goals> </execution> </executions> </plugin>
あとは、「mvn verify」で。
$ mvn clean verify
ここでは「clover:instrument」を使用したので、テストが2回動きますが…。