Measuring the coverage of your tests
アプリケーションのテストカバレッジを測定する方法をご紹介します。このガイドでは、以下の内容をカバーしています:
-
ユニットテストのカバレッジを測定する
-
統合テストのカバレッジを測定する
-
ユニットテストと統合テストの実行を分離する
-
全テストのカバレッジを統合する
ネイティブモードではコードカバレッジはサポートされていませんのでご注意ください。
1. 前提条件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 17+がインストールされ、
JAVA_HOMEが適切に設定されていること -
Apache Maven 3.9.16
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
-
アプリケーションのテストガイド が完了済であること
2. アーキテクチャ
このガイドで作成するアプリケーションは、サービスを使用するために依存性の注入に依存した単なる Jakarta REST エンドポイント (hello world) です。サービスは JUnit でテストされ、エンドポイントには @QuarkusTest アノテーションが付けられます。
3. ソリューション
次の章で紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。しかし、完成した例にすぐに進むことができます。Git リポジトリをクローンします: git clone https://github.com/quarkusio/quarkus-quickstarts.git 、または archive をダウンロードします。
ソリューションは tests-with-coverage-quickstart ディレクトリ にあります。
4. 簡単なプロジェクトと2つのテストから始める
Quarkus Mavenプラグインで作成した空のアプリケーションから始めてみましょう:
Windowsユーザーの場合:
-
cmdを使用する場合、(バックスラッシュ
\を使用せず、すべてを同じ行に書かないでください)。 -
Powershellを使用する場合は、
-Dパラメータを二重引用符で囲んでください。例:"-DprojectArtifactId=tests-with-coverage-quickstart"
ここで、アプリケーションをテストで適切にカバーするために必要な要素をすべて追加していきます。
まず、helloエンドポイントを提供するJakarta RESTリソース:
package org.acme.testcoverage;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/hello")
public class GreetingResource {
private final GreetingService service;
@Inject
public GreetingResource(GreetingService service) {
this.service = service;
}
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("/greeting/{name}")
public String greeting(String name) {
return service.greeting(name);
}
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "hello";
}
}
このエンドポイントは、グリーティングサービスを利用しています:
package org.acme.testcoverage;
import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class GreetingService {
public String greeting(String name) {
return "hello " + name;
}
}
また、プロジェクトにはテストも必要です:
package org.acme.testcoverage;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Tag;
import java.util.UUID;
import static io.restassured.RestAssured.given;
import static org.hamcrest.CoreMatchers.is;
@QuarkusTest
public class GreetingResourceTest {
@Test
public void testHelloEndpoint() {
given()
.when().get("/hello")
.then()
.statusCode(200)
.body(is("hello"));
}
@Test
public void testGreetingEndpoint() {
String uuid = UUID.randomUUID().toString();
given()
.pathParam("name", uuid)
.when().get("/hello/greeting/{name}")
.then()
.statusCode(200)
.body(is("hello " + uuid));
}
}
5. Jacocoの設定
次に、Jacocoをプロジェクトに追加する必要があります。そのために、ビルドファイルに以下を追加する必要があります:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jacoco</artifactId>
<scope>test</scope>
</dependency>
testImplementation("io.quarkus:quarkus-jacoco")
このQuarkusエクステンションは、通常はJacoco Mavenプラグインで行われることすべての処理を行うため、追加の設定は必要ありません。
| Using both the extension and the plugin requires special configuration, if you add both you will get lots of errors about classes already being instrumented. The configuration needed is detailed below. |
6. マルチモジュールプロジェクトでの作業
3.2 までは、 data-file と report-location は常にモジュールのビルド出力ディレクトリからの相対パスでした。このため、すべてのカバレッジを1つの親ディレクトリに集約したいようなマルチモジュールプロジェクトでは作業できませんでした。 3.3 から、 data-file または report-location を指定すると、そのパスがそのまま使われます。以下は surefire プラグインの設定例です:
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<quarkus.jacoco.data-file>${maven.multiModuleProjectDirectory}/target/jacoco.exec</quarkus.jacoco.data-file>
<quarkus.jacoco.reuse-data-file>true</quarkus.jacoco.reuse-data-file>
<quarkus.jacoco.report-location>${maven.multiModuleProjectDirectory}/target/coverage</quarkus.jacoco.report-location>
</systemPropertyVariables>
</configuration>
</plugin
If you need to configure the argLine property of the Surefire plugin (e.g. for setting memory parameters), you need to use Maven late property evaluation, otherwise the Jacoco agent will not be correctly added, and regular JUnit tests and Quarkus ComponentTest will not get covered. Example: <argLine>@{argLine} -your -extra -arguments</argLine>.
|
7. カバレッジ付きテストの実行
mvn verify を実行すると、テストが実行され、その結果が target/jacoco-reports に出力されます。 quarkus-jacoco のエクステンションを使えば、これだけでJacoco はすぐに動作します。
これにはいくつかの設定オプションがあります:
ビルド時に固定される設定プロパティ - 他のすべての設定プロパティは、実行時にオーバーライド可能
Configuration property |
タイプ |
デフォルト |
|---|---|---|
Whether or not the Jacoco extension is enabled. Environment variable: Show more |
boolean |
|
The Jacoco data file. The path can be relative (to the project/module root) or absolute. Environment variable: Show more |
string |
|
Whether to reuse ( Environment variable: Show more |
boolean |
|
If Quarkus should generate the Jacoco report Environment variable: Show more |
boolean |
|
Encoding of the generated reports. Environment variable: Show more |
string |
|
Name of the root node HTML report pages. Environment variable: Show more |
string |
|
Footer text used in HTML report pages. Environment variable: Show more |
string |
|
Encoding of the source files. Environment variable: Show more |
string |
|
A list of class files to include in the report. May use wildcard characters (* and ?). When not specified everything will be included. 例えば
Environment variable: Show more |
文字列のリスト |
|
A list of class files to exclude from the report. May use wildcard characters (* and ?). When not specified nothing will be excluded. 例えば
Environment variable: Show more |
文字列のリスト |
|
The location of the report files. The path can be relative (to the project/module root) or absolute. Environment variable: Show more |
string |
|
タイプ |
デフォルト |
|
The maven groupId of the artifact. Environment variable: Show more |
string |
required |
The maven artifactId of the artifact (optional). Environment variable: Show more |
string |
|
The maven classifier of the artifact (optional). Environment variable: Show more |
string |
|
If set to Environment variable: Show more |
boolean |
|
|
マルチモジュールのプロジェクトを扱う場合、コードカバレッジが適切に機能するためには、上流のモジュールが適切に インデックスされている 必要があります。 |
8. QuarkusTestを使用していないテストのカバレッジ
Quarkusの自動Jacoco設定は、 @QuarkusTest でアノテーションされたテストに対してのみ機能します。他のテストのカバレッジもチェックしたい場合は、Jacoco mavenプラグインを利用する必要があります。
quarkus-jacoco エクステンションを pom.xml に含めるのに加えて、以下のような設定が必要になります:
This config will only work if at least one @QuarkusTest is being run. If you are not using @QuarkusTest then
you can simply use the JaCoCo plugin in the standard manner with no additional config.
|
8.1. 結合テストのカバレッジ
結合テストからコードカバレッジデータを取得するには、以下の要件を満たす必要があります:
-
ビルドされたアーティファクトがjarであること(コンテナやネイティブバイナリではないこと)。
-
Jacocoがビルドツールで設定されていること。
-
アプリケーションは、
quarkus.package.write-transformed-bytecode-to-build-outputがtrueに設定してビルドされていること
Setting quarkus.package.write-transformed-bytecode-to-build-output=true should be done with caution and only if subsequent builds are done in a clean environment - i.e. the build tool’s output directory has been completely cleaned.
|
pom.xml で、Jacocoのプラグイン設定を以下のように追加します。これにより、結合テストのデータをユニットテストと同じ保存先のファイルに追加し、結合テストが完了した後にjacocoレポートを再構築することで、包括的なコードカバレッジレポートを作成します。
<build>
...
<plugins>
...
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
... (1)
<execution>
<id>default-prepare-agent-integration</id>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/jacoco-quarkus.exec</destFile>
<append>true</append>
</configuration>
</execution>
<execution>
<id>report</id>
<phase>post-integration-test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/jacoco-quarkus.exec</dataFile>
<outputDirectory>${project.build.directory}/jacoco-report</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
| 1 | すべてのexecutionsは同じ <plugin> の定義にあるはずなので、すべてつなげてください。 |
Jacocoエージェントで結合テストをjarとして実行するには、 pom.xml に以下を追加します。
<build>
...
<plugins>
...
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
<quarkus.test.arg-line>${argLine}</quarkus.test.arg-line>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
Sharing the same value for quarkus.test.arg-line might break integration test runs that test different types of Quarkus artifacts. In such cases, the use of Maven profiles is advised.
|