【发布时间】:2015-02-22 09:50:14
【问题描述】:
我正在尝试让 jacoco+gradle 一起工作。看看这个论坛,似乎有些人已经成功地做到了。但是当我尝试时,我遇到了一个奇怪的异常。
我做了什么:
1.下载gradle 2.2.1并配置环境变量等
2.从http://www.eclemma.org/jacoco/下载jacoco 0.7.1
3.添加:
apply plugin: 'jacoco'
和
buildTypes {
debug
{
testCoverageEnabled true
...
在 build.gradle 中
4.运行 gradle build
5.我收到一条错误消息,提示找不到 jacoco 代理 jar,等等。错误消息显示它试图搜索 C:\Program Files (x86)\Android\android-sdk\extras\android\m2repository 下的文件。 ..等等
6.我手动解压了jacoco的jar文件,放到提到错误信息的地方,错误信息消失了。
7.然后我运行了 gradle build。运行内置的 instrumentDebug 任务时出现以下新错误:
Caused by: : taskdef A class needed by class org.jacoco.ant.InstrumentTask cannot be found: org/jacoco/core/runtime/IExecutionDataAccessorGenerator using the classloader AntClassLoader[C:\Program Files (x86)\Android\android-sdk\extras\android\m2repository\org\jacoco\org.jacoco.ant\0.7.1.201405082137\org.jacoco.ant-0.7.1.201405082137.jar]
at org.apache.tools.ant.taskdefs.Definer.addDefinition(Definer.java:612)
at org.apache.tools.ant.taskdefs.Definer.execute(Definer.java:237)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:292)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
at org.gradle.api.internal.project.ant.BasicAntBuilder.nodeCompleted(BasicAntBuilder.java:77)
at org.gradle.api.internal.project.ant.BasicAntBuilder.doInvokeMethod(BasicAntBuilder.java:92)
at com.android.build.gradle.internal.coverage.JacocoInstrumentTask.instrument(JacocoInstrumentask.groovy:51)
at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:63)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:218)
at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:211)
Caused by: java.lang.ClassNotFoundException:
at org.jacoco.core.runtime.IExecutionDataAccessorGenerator
at org.apache.tools.ant.AntClassLoader.findClassInComponents(AntClassLoader.java:1366)
at org.apache.tools.ant.AntClassLoader.findClass(AntClassLoader.java:1315)
at org.apache.tools.ant.AntClassLoader.loadClass(AntClassLoader.java:1068)...
当我使用进程监视器(我的开发机器是 Win 7)时,我看到无法访问 org.jacoco.core-0.7.1.201405082137.jar,org.jacoco.ant.InstrumentTask 类驻留在其中。所以我认为 gradle 没有正确地将文件路径传递给 org.apache.tools.ant.AntClassLoader。
我尝试了以下方法,但都没有奏效:
- 将所有 jacoco jar 文件添加到 CLASSPATH 环境变量中。
- 将 jacoco jar 文件添加到 ant libs、gradle libs、gradle libs/plugins、文件夹。
- 查看gradle 2.2.1的源码。此刻一头雾水……
有人知道如何解决这个问题吗?
提前致谢!
编辑:
主要目的是:
1.让 jacoco 构建一个检测的 apk 文件
2。手动测试apk文件(非自动测试)
3.让 jacoco 生成覆盖率报告
更新: 我刚刚发现在执行 InstrumentDebug 任务时,gradle 使用以下命令启动了一个新进程:
"C:\Program Files\Java\jdk1.8.0_25\bin\java.exe" -XX:MaxPermSize=512m -Xmx2048m -Dfile.encoding=UTF-8 -Duser.country=CN -Duser.language= zh -Duser.variant -cp D:\gradle-2.2.1\gradle-2.2.1\lib\gradle-launcher-2.2.1.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 2.2.1 D:\ gradle-2.2.1\gradle-2.2.1\daemon 120000 744501ac-32c1-4930-82bd-59e0a9e2b92d -XX:MaxPermSize=512m -Xmx2048m -Dfile.encoding=UTF-8 -Duser.country=CN -Duser.language= zh -Duser.variant
如您所见,类路径是硬编码的,它会覆盖环境变量中定义的内容。所以找不到需要的jacoco核心库,导致了这个问题。我现在正在尝试查看此过程从哪里开始以及是否有办法更改 -cp 选项。
更新 2: 我终于发现这个过程是由 gradle-launcher-2.2.1.jar 启动的。请参见下面的代码。我现在正在尝试查看是否可以更改 DefaultModuleRegistry 并使 registry.getGradleHome() == null。 同时有成功使用过jacoco+gradle的朋友可以告诉我你用的是哪个版本的gradle吗?
public DaemonStartupInfo startDaemon()
{
DefaultModuleRegistry registry = new DefaultModuleRegistry();
Set<File> bootstrapClasspath = new LinkedHashSet();
bootstrapClasspath.addAll(registry.getModule("gradle-launcher").getImplementationClasspath().getAsFiles());
if (registry.getGradleHome() == null)
{
bootstrapClasspath.addAll(registry.getFullClasspath());
}
if (bootstrapClasspath.isEmpty()) {
throw new IllegalStateException("Unable to construct a bootstrap classpath when starting the daemon");
}
new JvmVersionValidator().validate(this.daemonParameters);
List<String> daemonArgs = new ArrayList();
daemonArgs.add(this.daemonParameters.getEffectiveJavaExecutable());
List<String> daemonOpts = this.daemonParameters.getEffectiveJvmArgs();
LOGGER.debug("Using daemon opts: {}", daemonOpts);
daemonArgs.addAll(daemonOpts);
daemonArgs.add("-cp");
daemonArgs.add(CollectionUtils.join(File.pathSeparator, bootstrapClasspath));
daemonArgs.add(GradleDaemon.class.getName());
daemonArgs.add(GradleVersion.current().getVersion());
daemonArgs.add(this.daemonDir.getBaseDir().getAbsolutePath());
daemonArgs.add(String.valueOf(this.daemonParameters.getIdleTimeout()));
daemonArgs.add(this.daemonParameters.getUid());
...
}
【问题讨论】:
-
您是否遵循 Gradle 指南(第 34 章):gradle.org/docs/current/userguide/jacoco_plugin.html。我还没有尝试过 Gradle 2.2.1,但是,我的问题是,您是在尝试使用“单元测试”还是使用“集成/接受/Selenium/etc GUI 测试”来获取主要源代码的代码覆盖率?如果它正在使用您的 UNIT 测试,那么当您运行“gradle clean build”时,Gradle 将免费执行此操作。如果您想使用非单元测试对主要源代码进行代码覆盖,那么您必须将 jacocoagent 附加到目标 JVM(例如:在目标服务器的 Tomcat JVM 中,其中运行应用程序的 .war)。
-
另外,粘贴您的 build.gradle。
-
@ArunSangal,感谢您的回复。我已经更新了我的目的。我现在被困在#1。我的 build.gradle 没有什么特别之处。我刚刚添加了第 3 步提到的内容。