使用 EclEmma 和 Eclipse 获取 "no coverage data has been collected" 消息

Getting a "no coverage data has been collected" message using EclEmma and Eclipse

我最近突然遇到了这个非常烦人的问题。 运行 我启用了 EclEmma 覆盖率的单元测试导致以下对话框 window 从 Eclipse 中弹出:

对于搜索引擎,它显示为:

No coverage data has been collected during this coverage Session.
Please do not terminate the Java process manually from Eclipse.

没有为我的项目中的任何 class 提供覆盖率信息。 不用说,我不会手动终止 Java 进程。为了尝试修复它,我:重新导入我的项目,升级 Java,重新安装 Emma,重新启动我的 Macbook Pro,确保临时文件系统 space 看起来不错,还有 20 件我现在忘记的事情。

我终于注意到只有我的几个开源项目产生了这个错误,因此决定减少我的一个测试。这是重现问题的最小测试。

测试 class 我正在尝试覆盖:

public class Foo {
    public void method() {
        System.out.println("hello");
    }
}

这是驱动它的 junit class:

public class EclEmmaFailureTest {
    @Test(timeout = 100000) // if you remove the timeout it works
    public void testStuff() {
        // this should cover Foo 100%
        new Foo().method();
        // if you comment this out stuff works
        org.apache.commons.logging.LogFactory.getLog(getClass());
    }
}

测试中的 commons-log Log 引用似乎破坏了覆盖集合。我在以下位置发布了一个工作回购:https://github.com/j256/eclemma-failure

如果您执行以下任一操作,问题就会消失:

我是 运行 Emma 版本 3.1.3,我的测试程序依赖于 commons-logging 版本 1.2。

我有一个降级路径可以解决这个问题并让我重新工作,但是 Junit 4.12 有安全问题。我很好奇是否有人知道导致此问题的 junit 或 emma 的具体问题。

Jacoco 也受到影响,这并不奇怪。这是我的覆盖率报告 before upgrading to Junit 4.13.1 showing 80% coverage and here it is afterwards with no coverage information,显示 0%。

谢谢。

这里不使用 EMMA,即使名称 EclEmma 可能暗示它。事实上,EclEmma 于 2006 年开始作为 EMMA 的 Eclipse 集成。但是 9 多年前,since EclEmma 2.0, EMMA has been replaced by JaCoCo,一个由 EclEmma 团队创建的 Java 的免费代码覆盖率库。

由于测试中应用程序 and/or 中的代码更改使问题消失,因此收集覆盖率数据但未显示的可能性很小。因此,唯一可能剩下的原因是 某些东西正在干扰 JaCoCo 收集数据。 FAQ of JaCoCo 命名可能是什么:

Why does a class show as not covered although it has been executed?

First make sure execution data has been collected. For this select the Sessions link on the top right corner of the HTML report and check whether the class in question is listed. If it is listed but not linked the class at execution time is a different class file. Make sure you're using the exact same class file at runtime as for report generation. Note that some tools (e.g. EJB containers, mocking frameworks) might modify your class files at runtime. Please see the chapter about class ids for a detailed discussion.

为确保这不是 缓存问题,请尝试对代码进行细微更改是否也能使问题消失。

您列出的使问题消失的事情非常不同,但都可能影响时间,这表明 并发问题 。您可以尝试更改测试的顺序 and/or 在某些地方添加 Thread.sleep() 以查看是否有任何改变。

但是,在你的情况下,根本原因尚不清楚, 没有最小的可重现的例子(如果它可能很难提供是并发问题)。

更新:

As Evgeny Mandrikov pointed out,根本问题确实是 JUnit 4.13 和 4.13.1 的并发 问题(包括所有 4.13-beta-* 和 4.13-rc-*版本,但以前版本的 JUnit 不受影响):

JUnit 4 issue #1652: Timeout ThreadGroups should not be destroyed

此问题已针对即将发布的 JUnit 4.13.2 版本修复

以下内容可用作 解决方法 以防止线程组 destroyed 并因此 JaCoCo 丢失其收集的数据(通过向其中添加虚拟线程组):

/** Workaround for already fixed JUnit 4 issue #1652 (<https://github.com/junit-team/junit4/issues/1652>) */
public static void workaround_for_junit4_issue_1652() {
    String version = junit.runner.Version.id();
    if (!"4.13.1".equals(version) && !"4.13".equals(version))
        fail("Workaround for JUnit 4 issue #1652 required for JUnit 4.13 and 4.13.1 only; actual version: "
           + version);
    Thread thread = Thread.currentThread();
    if (!"Time-limited test".equals(thread.getName())) fail("Workaround only required for a test with a timeout.");
    new Thread(thread.getThreadGroup(), new Runnable() {
        @Override
        public void run() {
            try {
                while (!thread.isInterrupted()) Thread.sleep(100);
            } catch (InterruptedException e) {}
        }
    }).start();
}

@Test(timeout = 42)
public void test() {
    workaround_for_junit4_issue_1652();
    // ...
}

No coverage data has been collected during this coverage Session. Please do not terminate the Java process manually from Eclipse.

这似乎是 4.13 版中引入的关于线程组的 Junit 问题。看到这个 github discussion and see this pull request。设置超时后,Junit 似乎一直在破坏线程组以处理卡住的线程问题,这没有让 Eclemma 有机会写出覆盖率信息。他们似乎已将线程组更改为守护线程,作为处理此问题的更好方法。

似乎唯一的解决办法是等待 4.13.2 发布,因为 4.13.1 之前的版本存在安全问题。

Looks like shutdown hooks are not executed the same way in 4.13 as it used to happen in 4.12 and thus the coverage failure.

感谢 Eclemma mailing list 对此的帮助。