Testng, Emma, Cobertura, покрытие и JDK 7 приводят к ClassFormatError и VerifyError
Я перешел на новейшую версию JDK 7, и у меня возникли проблемы с запуском юнит-теста testng на байт-код, который обрабатывается инструментом покрытия emma. Ни один из моих тестов не выполняется правильно, и для большинства из них я получаю такие ошибки.
java.lang.ClassFormatError: Illegal local variable table length 10 in method measurement.meter.AbstractSerialPortMeter.<init>(Lmeasurement/meter/SerialPort;)V at measurement.meter.Elc3133aTest.setUp(Elc3133aTest.java:42)
Я нашел здесь статью JSR 292 Goodness Fast Code Coverage Less 10k, в которой говорится, что "JSR 292 вводит новую инструкцию байт-кода invokedynamic, а также несколько новых видов констант пула констант. Это означает, что большинство инструментов, которые анализируют байт-коды, такие как ASM, BCEL, findbugs или EMMA должны быть обновлены, чтобы быть совместимыми с Java 7 ".
Проверена домашняя страница Эммы, но, похоже, она долгое время не обновлялась.
Кто-нибудь решил подобную проблему?
Я также пытался с Cobertura. Это выглядит работать немного лучше, но я получаю много исключений типа VerifyError
,
java.lang.VerifyError: Expecting a stackmap frame at branch target 85 in method measurement.meter.AbstractSerialPortMeter.close()V at offset 26
at measurement.meter.AbstractSerialPortMeterTest.setUp(AbstractSerialPortMeterTest.java:27)
6 ответов
Я была такая же проблема. К счастью, бета-версия работает с JDK 7.
Обновить ссылку на сайт: http://download.eclipselab.org/eclemma/beta/2.0.0/update/
Эта ссылка должна использоваться в Eclipse:
Help -> Install new software... -> Add...
Отдых должен быть легким;)
У меня была та же проблема с использованием плагина Maven Cobertura. Все тесты не пройдены при запуске из cobertura: отчет. Но все тесты прошли успешно, если они запускались прямо из плагина surefire. Как некоторые из вас уже сказали, проблема в том, что инструментарий боб-кода coberture не совместим с JDK7.
Здесь вы можете увидеть http://vikashazrati.wordpress.com/2011/10/09/quicktip-verifyerror-with-jdk-7/ что исключение связано с "средством проверки нового типа с атрибутами StackMapTable" (см.: -X:+ Использовать опцию JVM SplitVerifier в http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html).
Поэтому мое решение состоит в том, чтобы настроить плагин surefire для постоянного выполнения тестов с помощью JVM arg "-XX:-UseSplitVerifier. Он хорошо работает с инструментарием cobertura и без него.
Моя верная конфигурация в Maven:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12</version>
<configuration>
<argLine>-XX:-UseSplitVerifier</argLine>
</configuration>
</plugin>
Я получил Gradle 1.0M9, Java 7 и EMMA 2.1, работающие с патчами, предложенными здесь: используя аргумент jvm.
Подробности здесь... http://marcellodesales.wordpress.com/2012/04/03/running-emma-code-test-coverage-with-java-7-and-gradle-1-0m9/?preview=true&preview_id=179&preview_nonce=261e892908
configurations{
emma
}
dependencies {
// EMMS Code Coverage
emma "emma:emma:2.1.5320"
emma "emma:emma_ant:2.1.5320"
...
testCompile group: 'junit', name: 'junit', version: '4.9'
}
test {
// add EMMA related JVM args to our tests
jvmArgs "-XX:-UseSplitVerifier", "-Demma.coverage.out.file=$buildDir/tmp/emma/metadata.emma", "-Demma.coverage.out.merge=true"
doFirst {
println "Instrumenting the classes at " + sourceSets.main.output.classesDir.absolutePath
// define the custom EMMA ant tasks
ant.taskdef( resource:"emma_ant.properties", classpath: configurations.emma.asPath)
ant.path(id:"run.classpath") {
pathelement(location:sourceSets.main.output.classesDir.absolutePath)
}
def emmaInstDir = new File(sourceSets.main.output.classesDir.parentFile.parentFile, "tmp/emma/instr")
emmaInstDir.mkdirs()
println "Creating $emmaInstDir to instrument from " + sourceSets.main.output.classesDir.absolutePath
// instruct our compiled classes and store them at $buildDir/tmp/emma/instr
ant.emma(enabled: 'true', verbosity:'info'){
instr(merge:"true", destdir: emmaInstDir.absolutePath, instrpathref:"run.classpath",
metadatafile: new File(emmaInstDir, '/metadata.emma').absolutePath) {
instrpath {
fileset(dir:sourceSets.main.output.classesDir.absolutePath, includes:"**/*.class")
}
}
}
setClasspath(files("$buildDir/tmp/emma/instr") + configurations.emma + getClasspath())
}
// The report should be generated directly after the tests are done.
// We create three types (txt, html, xml) of reports here. Running your build script now should
// result in output like that:
doLast {
def srcDir = sourceSets.main.java.srcDirs.toArray()[0]
println "Creating test coverage reports for classes " + srcDir
def emmaInstDir = new File(sourceSets.main.output.classesDir.parentFile.parentFile, "tmp/emma")
ant.emma(enabled:"true"){
new File("$buildDir/reports/emma").mkdirs()
report(sourcepath: srcDir){
fileset(dir: emmaInstDir.absolutePath){
include(name:"**/*.emma")
}
txt(outfile:"$buildDir/reports/emma/coverage.txt")
html(outfile:"$buildDir/reports/emma/coverage.html")
xml(outfile:"$buildDir/reports/emma/coverage.xml")
}
}
println "Test coverage reports available at $buildDir/reports/emma."
println "txt: $buildDir/reports/emma/coverage.txt"
println "Test $buildDir/reports/emma/coverage.html"
println "Test $buildDir/reports/emma/coverage.xml"
}
}
Выполнение "теста Gradle" дает следующее:
marcello@hawaii:/u1/development/workspaces/open-source/interviews/vmware$ gradle test
:compileJava
:processResources UP-TO-DATE
:classes
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test
Instrumenting the classes at /u1/development/workspaces/open-source/interviews/vmware/build/classes/main
Creating /u1/development/workspaces/open-source/interviews/vmware/build/tmp/emma/instr to instrument from /u1/development/workspaces/open-source/interviews/vmware/build/classes/main
Creating test coverage reports for classes /u1/development/workspaces/open-source/interviews/vmware/src/main/java
Test coverage reports available at /u1/development/workspaces/open-source/interviews/vmware/build/reports/emma.
txt: /u1/development/workspaces/open-source/interviews/vmware/build/reports/emma/coverage.txt
Test /u1/development/workspaces/open-source/interviews/vmware/build/reports/emma/coverage.html
Test /u1/development/workspaces/open-source/interviews/vmware/build/reports/emma/coverage.xml
BUILD SUCCESSFUL
У меня была эта проблема. Обновление до 2.0.1.201112281951 с использованием торговой площадки Eclipse работало для меня.
Эмма работает, если вы не используете новые языковые функции (например, попробовать с ресурсами и т. Д.). Вы можете использовать Java 7, используя новые библиотеки (Paths, DirectoryStream и т. Д.). Я знаю, что это не будет решением вашей проблемы, но если вы хотите проверить только "как работает JDK 7", это может сработать...
Инструмент внутреннего покрытия IntelliJ IDEA 11 отлично работает для моего проекта с использованием оператора try с ресурсами, но мы не используем invokedynamic. Я думаю, что инструмент покрытия не включен в выпуск сообщества, только окончательный вариант.
Я еще не попробовал jacoco - туда, куда, похоже, ушло большинство бывших разработчиков Эммы.
Эквивалент ответа Педро Бальестероса для Java 8+:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.12.4</version>
<configuration>
<argLine>-noverify</argLine>
</configuration>
</plugin>
(Измените номер версии, чтобы он соответствовал используемой вами версии Surefire.)