Testng, Emma, Cobertura, покрытие и JDK 7 приводят к ClassFormatError и VerifyError
Я переключился на новейший JDK 7, и у меня возникают проблемы с запуском testng unit test по байтовому коду, который искажается с помощью инструмента покрытия 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 Инструмент покрытия кода хорошего качества Fast Less менее 10k,
в котором говорится, что "JSR 292 вводит новую инструкцию байт-кода invokedynamic, но также имеет несколько новых констант пула констант. Это означает, что большинство инструментов, которые анализируют байт-коды, такие как ASM, BCEL, findbugs или EMMA, должны быть обновлены, чтобы быть java 7 совместимый".
Проверьте домашнюю страницу Emma, но похоже, что она не обновлялась долгое время.
Кто-нибудь решил аналогичную проблему?
Я тоже пытался с Кобертурой. Он выглядит немного лучше, но я получаю много исключений типа 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)
Ответы
Ответ 1
У меня была такая же проблема.
К счастью, бета работает с JDK 7.
Обновить ссылку сайта: http://download.eclipselab.org/eclemma/beta/2.0.0/update/
Эта ссылка должна использоваться в Eclipse:
Help -> Install new software... -> Add...
Отдых должен быть легким;)
Ответ 2
У меня была такая же проблема с использованием плагина maven cobertura. Все тесты не удались при запуске из cobertura: report. Но все тесты удались, когда они запускались прямо из плагина surefire. Поскольку некоторые из вас уже сказали, что проблема заключается в том, что кодовое кодовое кодирование кода несовместимо с JDK7.
Здесь вы можете увидеть http://vikashazrati.wordpress.com/2011/10/09/quicktip-verifyerror-with-jdk-7/, что это исключение связано с "новым типом проверки с атрибутами StackMapTable" (см.: -X: + UseSplitVerifier JVM в http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html).
Итак, мое решение состоит в том, чтобы настроить surefire-plugin, чтобы всегда выполнять тесты с помощью 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>
Ответ 3
Я получил 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 test" дает следующее:
[email protected]:/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
Ответ 4
Эмма работает, если вы не используете новые языковые функции (например, try-with-resources и т.д.). Вы можете использовать Java 7, используя новые библиотеки (Paths, DirectoryStream и т.д.).
Я знаю, что это не будет решением вашей проблемы, но если вы хотите только проверить "как работает JDK 7", это может сработать...
Ответ 5
У меня была эта проблема. Для меня работало обновление до 2.0.1.201112281951 с использованием рынка Eclipse.
Ответ 6
IntelliJ IDEA 11 инструмент для внутреннего покрытия отлично работает для моего проекта с использованием try-with-resources, оператора алмаза, но мы не используем invokedynamic. Я думаю, что инструмент охвата не включен в редакцию сообщества, только окончательный.
Мне еще предстоит попробовать jacoco - там, где, по-видимому, уехало большинство бывших разработчиков emma.
Ответ 7
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.)