我想减少我们的构建(使用ant)运行测试所需的时间。目前我使用默认的forkMode
,它在每个测试类上派生一个新的vm(perTest
)。
我正在考虑切换到forkMode="once"
,但我不确定这是否会以某种方式耦合测试,并可能在运行测试后给我假阳性和/或假阴性结果。
问题:
-
每个测试用例是否都会获得一个新的ClassLoader,从而使以前运行的所有静态引用不再可访问/可见?
-
是否存在导致测试依赖性/测试方法耦合的其他因素,这些因素可能会改变行为(除了我没有使用的本机库加载)
- 垃圾收集/终结是怎么回事?它们是在每次测试后运行的吗?(我不依赖它们,但我只想了解完整的情况)
更新
根据目前的答案,在使用forkMode时,junit似乎总是在每个vm/fork的所有测试用例之间共享一个类加载器。(所以forkMode="once"确实意味着所有测试都有一个类加载器)
这有很多优点(更快的测试,可能会因为静态耦合而导致测试失败),但也有一些缺点(静态耦合只有在使用共享类加载器时才有效->误报)
- 测试运行程序将有效地为所有测试创建一个单独的套件并运行它们,这样就只涉及一个类加载器
- 是的,这意味着静态数据将在测试之间共享,这偶尔会很方便,但会迫使您减少子句之间的静态耦合,这是一件好事
- 通常没有任何明确的GC,但你可以自己做
一般来说,在一个虚拟机中运行所有测试是一件好事。它迫使您查看静态耦合,并且速度要快得多。至关重要的是,这也是IDE运行它们的方式,这确实是测试应该运行的方式——尽可能接近编译的频率。
请注意,默认模式为每个测试用例(即类)分叉一个新的VM,而不是为每个测试(即方法)分叉。在我目前正在测试的应用程序中,当我为多个测试重用VM时,会出现一些问题:对象和状态是早期测试遗留下来的,并阻止了后期测试的工作。如果您的应用程序结构良好,并且测试是严格自包含的,那么这可能不是问题。我怀疑垃圾收集在每次测试后都会自动运行:众所周知,在任何情况下都很难确保在任何给定的时间调用它。
看看Stefan关于这件事的博客文章,我大胆猜测:
- 您将只获得forkMode="once"的单个类加载器
- 您将无法再访问Ant环境
- GC将在派生的GC中执行(如果forceMode="once"),这意味着在每次测试运行后都不会执行