2015-07-30 11 views
9

Sto generando report jacoco utilizzando jacoco: report tag. sto ottenendo gli errori come:generatore di report di copertura codice jacoco che mostra errore: "Classes in bundle" Report copertura del codice "non corrisponde con i dati di esecuzione"

[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. 

Il destinatario del rapporto formica assomiglia:

<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> 

Il così generato è quello di utilizzare solo ./code/src. Allora perché sta dando tali errori. Qualche idea?

+0

Aggiungi come viene generato executiondata ('$ {jacocoexec.filename}')? Ci dovrebbe essere un bersaglio separato che esegua il compito 'jacoco: coverage'. Metti questo obiettivo alla domanda pure. –

+0

aggiungendo il parametro -javaagent durante l'esecuzione del test case: -javaagent: JaCoCoProject/lib/jacocoagent.jar = destfile = JaCoCoProject/jacoco.exec, output = file – anon

+1

si prega di condividere il file di build completo. Tutto quello che l'errore sta dicendo è che hai strumentato un barattolo, hai eseguito test. Quelle classi non provengono da "./jar/abc.jar". Non è sufficiente abbinare le classi per nome. devono corrispondere al "classID" visto da jacoco- il che significa che anche se ricompilate, le classi sono diverse. – Jayan

risposta

4

JaCoCo richiede gli stessi file di classe per la generazione di report utilizzati al momento dell'esecuzione. A causa di diversi compilatori e/o altri strumenti che modificano le classi, le classi potrebbero essere diverse.

13

Si sta ottenendo l'errore relativo a classID. Questo è un concetto descritto in dettaglio nel sito di JaCoCo docs. http://www.eclemma.org/jacoco/trunk/doc/classids.html. Questo è un passo fondamentale per supportare più versioni di classe (un server delle applicazioni per esempio) nella stessa JVM.

Copia parte di esso qui per visibilità.

Quali sono gli ID di classe e come vengono creati?

ID di classe sono valori interi a 64 bit, ad esempio in 0x638e104737889183 notazione esadecimale. Il loro calcolo è considerato un dettaglio di implementazione di JaCoCo. Attualmente gli ID vengono creati con un checksum CRC64 del file di classe non elaborato.

Cosa può causare ID di classe diversi?

ID di classe sono identici per lo stesso file di classe solo (byte per byte). Ci sono un paio di motivi per cui potresti ottenere diversi file di classe. Prima compilazione file sorgente Java si tradurrà nei file di classe diverse se si utilizza un diverso tool chain:

  • diverso compilatore fornitore (ad esempio Eclipse vs Oracle JDK)

  • versioni del compilatore diverse

  • diverse impostazioni del compilatore (ad esempio, eseguire il debug vs non-debug)

Anche i file di classe di post-elaborazione (offuscamento, AspectJ, ecc.) Modificano in genere i file di classe. JaCoCo funzionerà bene se usi semplicemente gli stessi file di classe per runtime e per analisi. Quindi la catena di strumenti per creare questi file di classe non ha importanza.

Anche se i file di classe sul file system sono gli stessi, è possibile che le classi viste dall'agente di runtime JaCoCo siano diverse comunque. Ciò accade in genere quando un altro agente Java viene configurato prima che l'agente JaCoCo oi caricatori di classi speciali pre-elaborino i file di classe.candidati tipici sono:

  • quadri beffardo
  • I server di applicazioni
  • Persistenza quadri

La stessa pagina copre le possibili soluzioni.

Quali soluzioni alternative esistono per gestire le classi modificate in runtime?

Se le classi vengono modificati in fase di esecuzione nella configurazione ci sono alcune soluzioni per rendere JaCoCo lavorare in ogni modo:

  • Se si utilizza un altro agente Java assicurarsi che l'agente JaCoCo è specificato in un primo momento nella riga di comando. In questo modo l'agente JaCoCo dovrebbe vedere i file di classe originali.
  • Specificare l'opzione classdumpdir dell'agent JaCoCo e utilizzare le classi dumped alla generazione del report. Tieni presente che verranno scaricate solo le classi caricate, ovvero le classi non eseguite affatto non verranno visualizzate nel tuo rapporto come non coperte.
  • Utilizza la strumentazione offline prima di eseguire i test. In questo modo le classi vengono strumentate da JaCoCo prima che qualsiasi modifica del runtime possa avvenire. Si noti che in questo caso il report deve essere generato con le classi originali, non con quelle strumentate.

Redatta il 22-02-2017

Come usare Offline Strumentazione: Usa sotto compito fornito da 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 

Ora generare report utilizzando il comando "gradlew test jacocoTestReport".

+2

Grazie per aver aggiunto questa risposta. è abbastanza utile per comprendere la struttura jacoco e i concetti associati. – anon

+0

@ Jayan: La tua risposta è corretta ma molto difficile da capire cosa devo fare esattamente per risolvere il problema. Se riesci a fornire qualche frammento di codice, per me sarà molto più facile.Hai scritto la risposta considerando che la persona che leggerà questo avrà una buona comprensione di come funziona Jacoco. –

+1

@ Jayan: Modificato la risposta e aggiunto un'attività che ho usato per la strumentazione offline. Per favore ricontrolla. –