Measuring the coverage of your tests
アプリケーションのテストカバレッジを測定する方法をご紹介します。このガイドでは、以下の内容をカバーしています:
-
ユニットテストのカバレッジを測定する
-
統合テストのカバレッジを測定する
-
ユニットテストと統合テストの実行を分離する
-
全テストのカバレッジを統合する
ネイティブモードではコードカバレッジはサポートされていませんのでご注意ください。
1. 前提条件
このガイドを完成させるには、以下が必要です:
-
約15分
-
IDE
-
JDK 11+ がインストールされ、
JAVA_HOMEが適切に設定されていること -
Apache Maven 3.8.6
-
使用したい場合は、 Quarkus CLI
-
ネイティブ実行可能ファイルをビルドしたい場合、MandrelまたはGraalVM(あるいはネイティブなコンテナビルドを使用する場合はDocker)をインストールし、 適切に設定していること
-
アプリケーションのテストガイド が完了済であること
2. アーキテクチャ
このガイドで構築されたアプリケーションは、サービスを使用するために依存性インジェクションに依存した JAX-RS エンドポイント (hello world) に過ぎません。サービスは JUnit 5 でテストされ、エンドポイントには @QuarkusTest のアノテーションが付けられます。
3. ソリューション
次の章で紹介する手順に沿って、ステップを踏んでアプリを作成することをお勧めします。しかし、完成した例にすぐに進むことができます。Git リポジトリをクローンします: git clone https://github.com/quarkusio/quarkus-quickstarts.git 、または archive をダウンロードします。
ソリューションは tests-with-coverage-quickstart directory にあります。
4. 簡単なプロジェクトと2つのテストから始める
Quarkus Mavenプラグインで作成した空のアプリケーションから始めてみましょう:
ここで、アプリケーションをテストで適切にカバーするために必要な要素をすべて追加していきます。
最初に、helloエンドポイントを提供するアプリケーション:
package org.acme.testcoverage;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.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 javax.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. カバレッジ付きテストの実行
mvn verify を実行すると、テストが実行され、その結果が target/jacoco-reports に出力されます。 quarkus-jacoco のエクステンションを使えば、これだけでJacoco はすぐに動作します。
これにはいくつかの設定オプションがあります:
ビルド時に固定される設定プロパティ - それ以外の設定プロパティは実行時に上書き可能
タイプ |
デフォルト |
|
|---|---|---|
The jacoco data file 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 |
文字列のリスト |
|
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 |
文字列のリスト |
|
The location of the report files. Environment variable: Show more |
string |
|
7. 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.
|
7.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.
|