【问题标题】:Exclude specific tests from being run in parallel in jUnit排除特定测试在 jUnit 中并行运行
【发布时间】:2014-07-17 18:58:12
【问题描述】:

我最近偶然发现了一种通过 jUnit 并行执行测试的简单方法,方法是在 java 项目的 pom.xml 文件中指定以下内容:

<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-surefire-plugin</artifactId>
 <configuration>
  <parallel>classes</parallel>
 </configuration>
</plugin>

我发现有 2 个测试类(我们称它们为“badtestclass1”和“badtestclass2”)由于其中测试的编写方式而不断受到这种并行执行的惩罚。理想情况下,我会重构这些测试类以使其表现得更好,但在此期间,我想知道是否有一种巧妙的方法可以“排除”这些特定类的并行执行。基本上,有没有办法并行执行其他所有内容,然后按顺序执行这两个(或其他顺序,没关系)。会像下面这样工作吗?

<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-surefire-plugin</artifactId>
 <configuration>
  <parallel>classes</parallel>
  <excludes>
   <excludesFile>badtestclass1</excludesFile>
   <excludesFile>badtestclass2</excludesFile>
  </excludes>
 </configuration>
</plugin>

【问题讨论】:

    标签: java maven parallel-processing junit4


    【解决方案1】:

    您可以使用 jcip @NotThreadSafe 注释您不希望并行化的类,并保留您在开始示例中的安全配置。这样,只要 Surefire 找到一个带注释的类,它就会在单个线程中执行它。在“并行测试执行和单线程执行”段落中对 here 进行了解释。

    【讨论】:

      【解决方案2】:

      @polaretto 的 answer 建议使用 jcip @NotThreadSafe 注释,它与构建中的 surefire 插件一起使用,但不适用于命令行 mvn test。 @patson-luk 的 answer 走在正确的轨道上,不幸的是,通过在默认配置中排除“坏测试”,它仍然被排除在外,并且没有在单独的 &lt;execution&gt; 中运行。

      我设法使用以下配置使其正常工作:

      对于 JUnit 5,这些就足够了

      在我的src/test/resources/junit-platform.properties 文件中(或者你可以作为命令行参数传递):

      junit.jupiter.execution.parallel.enabled = true
      junit.jupiter.execution.parallel.mode.default = concurrent
      

      在我的非线程安全类的顶部(而不是 jcip 注释):

      import static org.junit.jupiter.api.parallel.ExecutionMode.SAME_THREAD;
      
      @Execution(SAME_THREAD)
      class SingleThreadedTest {
         // ...
      }
      

      对于 JUnit 4,将接受的答案修改如下:

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${maven-surefire-plugin.version}</version>
        <configuration>
          <!-- Skip default, define executions separately below -->
          <skip>true</skip>
        </configuration>
        <executions>
          <execution>
            <id>single-thread-test</id>
            <phase>test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <!-- Not thread safe, run separately -->
              <includes>
                <include>**/SingleThreadedTest.java</include>
              </includes>
              <forkCount>1</forkCount>
              <reuseForks>false</reuseForks>
              <threadCount>1</threadCount>
              <skip>false</skip>
            </configuration>
          </execution>
          <execution>
            <id>multi-thread-test</id>
            <phase>test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <excludes>
                <exclude>**/SingleThreadedTest.java</exclude>
              </excludes>
              <forkCount>4</forkCount>
              <reuseForks>true</reuseForks>
              <parallel>all</parallel>
              <useUnlimitedThreads>true</useUnlimitedThreads>
              <skip>false</skip>
            </configuration>
          </execution>
        </executions>
      </plugin>
      

      【讨论】:

      • 感谢分享!我正在使用 JUnit 5,我应该将 junit-platform.properties 放在 test/main/resources 或 src/main/resources 中,不知何故它似乎不适用于 PowermockRunner..
      • @KevD。我把它们放在src/test/resources,抱歉打错了。不过,应该可以在您的类路径上的任何地方工作。我已经迁移到使用junit-platform-maven-plugin,它将这些作为参数(See here)。
      【解决方案3】:

      在原始测试短语中排除这两个测试,然后创建一个新的执行,这两个类在单线程中运行? :)

      <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-surefire-plugin</artifactId>
          <configuration>
              <excludes>
                  <exclude>path/to/your/class/badtestclass1.java</exclude>
                  <exclude>path/to/your/class/badtestclass2.java</exclude>
              </excludes>
              <parallel>classes</parallel>
          </configuration>
      
          <executions>
              <execution>
                  <id>single-thread-test</id>
                  <phase>test</phase>
                  <goals>
                      <goal>test</goal>
                  </goals>
                  <configuration>
                      <includes>
                          <include>path/to/your/class/badtestclass1.java</include>
                          <include>path/to/your/class/badtestclass2.java</include>
                      </includes>
                      <threadCount>1</threadCount>
                  </configuration>
              </execution>
          </executions>
        </plugin>
      

      【讨论】:

      • 啊,我错过了测试类的路径以及不跳过这两个类的额外执行。谢谢好心的先生。
      • 有趣。当我复制这个 sn-p 测试 badtestclass1 和 2 被排除在正常运行之外,但是当我运行“mvn test”时它们不会自动连续运行。我需要打额外的电话吗?
      • @KannanEkanath 在这里聚会有点晚了。默认配置中的排除项阻止它们被单独包含在第二次执行中。为了让它工作,我必须跳过默认配置并执行两次。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-12
      • 1970-01-01
      • 2018-06-11
      • 2011-04-03
      • 1970-01-01
      • 1970-01-01
      • 2022-10-18
      相关资源
      最近更新 更多