JUnit测试:为什么Maven(Surefire)比在Eclipse上运行慢得多?

Gus*_*mos 6 java junit unit-testing spring-test maven

我正在开发一个相当大的应用程序,在套件上有大约260k LOC和大约1800个单元测试.一点背景:

  1. 多模块Maven项目
  2. 所有测试都在一个单独的模块上运行,JaCoCo用于检查覆盖范围.
  3. 测试在一些套件中组合在一起,然后套件包含在Surefire的配置中.
  4. 使用SpringJUnit4ClassRunner运行测试
  5. Surefire目前配置为使用相同的VM来构建和测试(forkCount等于1且reuseForks等于true).这样做我确信我正在使用Spring的静态上下文缓存的优点(ApplicationContext在每个测试中重复使用相同的)

当我们在开发虚拟机上运行测试时,使用Oracle JDK 7u79/80,我们会看到非常快速的测试.例如,具有50多种测试方法的相当大的测试类需要大约1:30m(包括上下文初始化时间)才能运行.

我们的基本Dev VM类似于:

  • 双核i5处理器(带超线程,4个虚拟线程)
  • 8GB RAM
  • 中档,SATA硬盘(5k或7k2 RPM)
  • 在客户端模式下运行Oracle JDK的 Windows 7 x64 (-client)

我们使用Jenkins作为CI服务器,Maven(3.2)负责构建过程.我们有Master + 2 Slaves架构.所有虚拟机完全相同:

  • 8个Xeon E5核心​​(真核)
  • 8 GB RAM
  • 为虚拟机提供服务的SSD LUN(平均吞吐量为1.2GB/s)
  • Debian Linux 8 x64
  • 服务器模式下的Oracle JDK

还记得那些通常需要1:30分钟才能运行Eclipse的测试吗?在服务器上,他们需要超过15分钟才能运行!这是我已经尝试过的事情(到目前为止没有成功.):

  • 将MAVEN_OPTS设置为固定堆大小(2GB堆),大型PermGen空间,调整GC设置,/ dev/urandom作为随机种子
  • 安装了32位JDK以使用我们在Dev Machines上使用的相同客户端模式
  • 调整Surefire的配置以增加内存,调整GC等(因为我不再使用分叉的VM来运行测试,所以我把它拿出来因为它不会改变任何东西.)

最重要的是,为什么Surefire的执行比在Eclipse上运行JUnit要慢得多?我现在已经在这几天刮过头了,这真的开始惹恼我了!当解决方案似乎如此接近但是它到目前为止,我讨厌它.

我无法在我的Dev机器上使用Maven进行测试,因为我无法分配所需的所有内存,但是运行大块的类(不是整个1.8k测试套件)仍然比在Eclipse上运行慢得多.

我理解Maven有所有这些阶段等等,但差别不应该是这么大.你不同意吗?

任何输入都将受到高度赞赏.我可以提供您认为必要的更多信息!

PS:Surefire v2.17,Maven 3.2.2,JUnit 4.12,Spring Test 3.2.13

非常感谢!

更新1

我尝试在CI服务器上停用JaCoCo以查看它是否影响了构建时间.它没有.执行时间保持不变.

Gus*_*mos 1

我在这方面已经取得了一些进展。正如我上面所说,这是一个多模块 (20+) Maven 应用程序。我们将所有测试分开在一个模块上,但 Surefire 的配置是在父 POM 上完成的,而不是在测试模块的 POM 上完成的。

在尝试了一切之后,我们决定将测试执行配置单独引入该模块,跳过所有其他模块。这使得套件的执行时间从约 45 英尺缩短至 22 英尺。我们对此感到摸不着头脑,一旦我们明白发生了什么,我会再次在这里发帖。

TL;DR:这张图片说明了一切。(题外话,工作安全)

感谢您的输入!