テストカバレッジの測定
アプリケーションのテストカバレッジを測定する方法をご紹介します。このガイドでは、以下の内容をカバーしています:
-
ユニットテストのカバレッジを測定する
-
統合テストのカバレッジを測定する
-
ユニットテストと統合テストの実行を分離する
-
全テストのカバレッジを統合する
ネイティブモードではコードカバレッジはサポートされていませんのでご注意ください。
1. 前提条件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 17+がインストールされ、
JAVA_HOME
が適切に設定されていること -
Apache Maven 3.9.9
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
-
アプリケーションのテストガイド が完了済であること
2. アーキテクチャ
このガイドで作成するアプリケーションは、サービスを使用するために依存性の注入を使用した Jakarta REST エンドポイント (hello world) です。サービスは JUnit 5 でテストされ、エンドポイントには @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プラグインで行われることすべての処理を行うため、追加の設定は必要ありません。
エクステンションとプラグインの両方を使用するには、特別な設定が必要です。両方を追加すると、すでにインスツルメンテーションされているクラスに関する多くのエラーが発生します。必要な設定の詳細は以下のとおりです。 |
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 module) 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. For instance:
Environment variable: Show more |
list of string |
|
A list of class files to exclude from the report. May use wildcard characters (* and ?). When not specified nothing will be excluded. For instance:
Environment variable: Show more |
list of string |
|
The location of the report files. The path can be relative (to the module) or absolute. Environment variable: Show more |
string |
|
マルチモジュールのプロジェクトを扱う場合、コードカバレッジが適切に機能するためには、上流のモジュールが適切に インデックスされている 必要があります。 |
8. QuarkusTestを使用していないテストのカバレッジ
Quarkusの自動Jacoco設定は、 @QuarkusTest
でアノテーションされたテストに対してのみ機能します。他のテストのカバレッジもチェックしたい場合は、Jacoco mavenプラグインを利用する必要があります。
quarkus-jacoco
エクステンションを pom.xml
に含めるのに加えて、以下のような設定が必要になります:
この設定は、少なくとも1つの @QuarkusTest が実行されている場合にのみ機能します。 @QuarkusTest を使用していない場合は、追加の設定をすることなく、通常の方法で Jacoco プラグインを使用することができます。
|
8.1. 結合テストのカバレッジ
結合テストからコードカバレッジデータを取得するには、以下の要件を満たす必要があります:
-
ビルドされたアーティファクトがjarであること(コンテナやネイティブバイナリではないこと)。
-
Jacocoがビルドツールで設定されていること。
-
アプリケーションは、
quarkus.package.write-transformed-bytecode-to-build-output
がtrue
に設定してビルドされていること
quarkus.package.write-transformed-bytecode-to-build-output=true は慎重に設定を行う必要があります。 後続のビルドがクリーンな環境で行われる場合、つまりビルドツールの出力ディレクトリが完全にクリーンである場合のみ行う必要があります。
|
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>
quarkus.test.arg-line で同じ値を共有すると、異なるタイプの Quarkus アーティファクトをテストする統合テストの実行が中断される場合があります。このような場合は、Mavenプロファイルの使用することをお勧めします。
|