Jacoco为仅一个测试类生成覆盖率报告

9
因此,假设我有一个测试。
@Test
public void testA(){
    new A().doSomthing();
}

假设有一个涉及IT技术的翻译任务需要您来完成,内容需要翻译的是一个方法doSomething()。在我的项目中,我有1000万个测试用例,而这个测试用例只是其中之一。一个小测试用例并没有太大作用。

现在让我们看一下我的doSomething方法:

public void doSomething() {
    if (var1)
        killMylSelf();
    else if (var2)
        killMyMother();
    else
        killMySelfAndMyMother();
}

因此,你可以看到该方法中有许多分支,因此调用其他具有更多分支的方法。当我运行testA时,我想知道我错过了哪些已执行的代码分支,我如何在不必运行所有单元测试且仅运行我关心的测试的情况下实现这一点?
记住,在回答问题“不必运行所有单元测试,只运行我关心的测试”时,请谨记这些神奇的话。

1
你尝试过使用“排除”或“包含”选项配置Maven或Ant插件吗? - Nico Van Belle
排除和包含是什么意思?@NicoVanBelle - Bhargav
如果你阅读JaCoCo文档,你会发现大多数(如果不是全部)目标都可以通过“排除”和“包含”参数进行配置。在这里,你可以定义哪些类应该被包括或排除在覆盖率报告之外。 - Nico Van Belle
我正在使用Maven,并应用了您提到的所有设置,但不幸的是mvn clean verify -Dtest=MyTestClassName#MyTestMethodName没有在target目录中创建任何测试报告或site文件夹。没有错误,构建成功完成,该目录中创建了其他文件夹。有什么想法吗? - Jack
1个回答

13

JaCoCo不会执行你的测试,它只是记录有关执行情况的信息。因此,测试的执行,包括单个测试的情况,完全取决于您用于执行测试的工具,而这些工具在您的问题中不幸没有提及。

如果您使用Maven作为构建工具,则测试的执行通常由maven-surefire-plugin完成和控制,该插件具有选项test以运行单个测试。以下是示例:

src/main/java/Example.java:

public class Example {
  public void doSomething(int p) {
    if (p == 1) {
      a();
    } else {
      b();
    }
  }

  private void a() {
    System.out.println("a");
  }

  private void b() {
    System.out.println("b");
  }
}

src/test/java/ExampleTest.java:

import org.junit.Test;

public class ExampleTest {
  @Test
  public void test1() {
    new Example().doSomething(1);
  }

  @Test
  public void test2() {
    new Example().doSomething(2);
  }
}

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>example</artifactId>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.20.1</version>
      </plugin>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>0.7.9</version>
        <executions>
          <execution>
            <id>default-prepare-agent</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
          </execution>
          <execution>
            <id>default-report</id>
            <goals>
              <goal>report</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

</project>

执行命令 mvn clean verify -Dtest=ExampleTest#test1 将在目录 target/site/jacoco 生成以下报告:

coverage of test1

执行mvn clean verify -Dtest=ExampleTest#test2将产生以下结果:

coverage of test2

这段内容涉及编程,展示了关于test1test2的覆盖率。

相比之下,执行mvn clean verify命令会运行所有测试,并产生以下结果:

coverage of all tests

关于使用clean的说明:文件target/jacoco.exec包含执行信息,并用于生成报告(参见代理选项destfile相应的jacoco-maven-plugin参数)。默认情况下,JaCoCo代理会将数据追加到这些文件中(参见代理选项append相应的jacoco-maven-plugin参数),因此在此示例中使用clean以防止在此文件中积累有关先前执行的数据。
如果您使用Gradle,则其也具有类似的功能-给定相同的源代码和build.gradle
apply plugin: 'java'
apply plugin: 'jacoco'

repositories {
  mavenCentral()
}

dependencies {
  testCompile 'junit:junit:4.12'
}

执行gradle clean test --tests ExampleTest.test1 jacocoTestReport将生成报告,其中包含test1的覆盖情况,与Maven的情况相同。
与Maven的示例类似,此示例中使用clean来防止在文件build/jacoco/test.exec中累积有关先前执行的数据 - 请参阅JaCoCo Gradle Pluginappend属性
如果您使用Eclipse IDE,则有EclEmma Eclipse插件将JaCoCo集成到Eclipse IDE中,并从Oxygen(4.7)版本开始默认包含在“Java开发人员的Eclipse IDE”中。使用它,您还可以在Eclipse IDE中获得单个测试的覆盖范围 - 在编辑器中,右键单击测试名称以获取上下文菜单,然后选择“Coverage As -> JUnit Test”。

在提到Android Studio之后,我需要说gradle吗?不管怎样,非常全面的答案,我很喜欢。如果在执行你的命令后运行的测试数量超过一个,我会非常失望的:( 我会尝试一下,并在12小时内告诉你!谢谢帮助。 - Bhargav
@Bhargav 在浏览器上搜索这个页面告诉我,“android”第一次出现在你的评论中,而不是问题中 ;) Android 有点不同,我不是 Android 专家,但根据 https://developer.android.com/studio/test/command-line.html,“Gradle 的 Android 插件”支持与我在答案中提到的“Gralde Java 插件”相同的选项“--tests”,用于执行单个测试。 - Godin
根据https://developer.android.com/studio/test/index.html#view_test_coverage,使用Android Studio在单个测试中运行覆盖率与在IntelliJ IDEA中运行带有覆盖率的测试没有区别。@Bhargav - Godin
@Bhargav 根据 https://docs.gradle.org/current/userguide/jacoco_plugin.html#sec:jacoco_tasks,`jacocoTestReport` 没有 dependensOn。再次提醒您的初始问题缺乏明确性,因为缺少具体的 最小完整可验证示例。虽然我相信有很多方法可以绕过 dependsOn,例如使用没有 dependsOn 的新任务,但是在没有具体示例的情况下,我认为猜测您特定配置的所有方面是不切实际的,也是浪费时间的行为,所以我不会再提出建议了。 - Godin
感谢您提供详细的解释。我正在使用Maven,并应用了您提到的所有设置,但不幸的是,mvn clean verify -Dtest=MyTestClassName#MyTestMethodName没有在target目录中创建任何测试报告或site文件夹。没有错误,构建成功完成,该目录中创建了其他文件夹。有什么想法吗? - Jack
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接