Jacoco:reportタグを使用してjacocoレポートを生成しています。次のようなエラーが表示されます。
[jacoco:report] Classes in bundle 'Code Coverage Report' do no match with execution data. For report generation the same class files must be used as at runtime.
[jacoco:report] Execution data for class xxxxx does not match.
[jacoco:report] Execution data for class yyyyy does not match.
Antレポートターゲットは次のようになります。
<target name="report">
<jacoco:report>
<executiondata>
<file file="${jacocoexec.dir}/${jacocoexec.filename}"/>
</executiondata>
<!-- the class files and optional source files ... -->
<structure name="Code Coverage Report">
<classfiles>
<fileset file="./jar/abc.jar"/>
</classfiles>
<sourcefiles>
<fileset dir="./code/src"/>
</sourcefiles>
</structure>
<!-- to produce reports in different formats. -->
<html destdir="${jacoco.report.dir}"/>
</jacoco:report>
</target>
abc.jar
そのように生成されるのは、./code/src
のみ。次に、なぜそのようなエラーが発生するのですか。何か案が?
ClassIDに関連するエラーが発生しています。これは、JaCoCo docs-siteで詳細に説明されている概念です。 http://www.eclemma.org/jacoco/trunk/doc/classids.html 。これは、同じJVMでクラスの複数のバージョン(たとえば、アプリケーションサーバー)をサポートするための重要なステップです。
可視性のために、ここにその一部をコピーします。
クラスIDとは何であり、どのように作成されますか?
クラスIDは64ビット整数値です。たとえば、16進表記の0x638e104737889183です。それらの計算は、JaCoCoの実装の詳細と見なされます。現在、IDは生のクラスファイルのCRC64チェックサムで作成されます。
異なるクラスIDの原因は何ですか?
クラスIDは、まったく同じクラスファイル(バイト単位)に対してのみ同一です。異なるクラスファイルを取得する理由はいくつかあります。最初にコンパイルするJavaソースファイルは、異なるツールチェーンを使用すると異なるクラスファイルになります。
異なるコンパイラベンダー(EclipseとOracle JDKなど)
異なるコンパイラバージョン
異なるコンパイラ設定(例:デバッグと非デバッグ)
また、クラスファイルの後処理(難読化、AspectJなど)は通常、クラスファイルを変更します。ランタイムと分析に同じクラスファイルを使用するだけであれば、JaCoCoはうまく機能します。したがって、これらのクラスファイルを作成するためのツールチェーンは重要ではありません。
ファイルシステム上のクラスファイルが同じであっても、JaCoCoランタイムエージェントから見たクラスはとにかく異なる可能性があります。これは通常、別のJavaエージェントがJaCoCoエージェントまたは特別なクラスローダーがクラスファイルを前処理する前に構成されている場合に発生します。典型的な候補は次のとおりです。
同じページで解決策を説明しています。
ランタイム変更クラスを処理するための回避策はありますか?
セットアップで実行時にクラスが変更された場合、とにかくJaCoCoを動作させるためのいくつかの回避策があります。
2017年2月22日に編集
オフライン計測の使用方法:Daniel Atallah が提供する以下のタスクを使用します。
//Additional SourceSets can be added to the jacocoOfflineSourceSets as needed by
project.ext.jacocoOfflineSourceSets = [ 'main' ]
task doJacocoOfflineInstrumentation(dependsOn: [ classes, project.configurations.jacocoAnt ]) {
inputs.files classes.outputs.files
File outputDir = new File(project.buildDir, 'instrumentedClasses')
outputs.dir outputDir
doFirst {
project.delete(outputDir)
ant.taskdef(
resource: 'org/jacoco/ant/antlib.xml',
classpath: project.configurations.jacocoAnt.asPath,
uri: 'jacoco'
)
def instrumented = false
jacocoOfflineSourceSets.each { sourceSetName ->
if (file(sourceSets[sourceSetName].output.classesDir).exists()) {
def instrumentedClassedDir = "${outputDir}/${sourceSetName}"
ant.'jacoco:instrument'(destdir: instrumentedClassedDir) {
fileset(dir: sourceSets[sourceSetName].output.classesDir, includes: '**/*.class')
}
//Replace the classes dir in the test classpath with the instrumented one
sourceSets.test.runtimeClasspath -= files(sourceSets[sourceSetName].output.classesDir)
sourceSets.test.runtimeClasspath += files(instrumentedClassedDir)
instrumented = true
}
}
if (instrumented) {
//Disable class verification based on https://github.com/jayway/powermock/issues/375
test.jvmArgs += '-noverify'
}
}
}
test.dependsOn doJacocoOfflineInstrumentation
"gradlew test jacocoTestReport"
コマンドを使用してレポートを生成します。
JaCoCoは、実行時に使用されるのとまったく同じクラスファイルをレポート生成に必要とします。異なるコンパイラやクラスを変更する他のツールが原因で、クラスが異なる場合があります。