[英]How can I use a custom runner when using categories in Junit?
I have a bunch of JUnit tests that extend my base test class called BaseTest
which in turn extends Assert
. 我有一堆JUnit测试扩展了我的基础测试类
BaseTest
,后者又扩展了Assert
。 Some of my tests have a @Category(SlowTests.class)
annotation. 我的一些测试有一个
@Category(SlowTests.class)
注释。
My BaseTest
class is annotated with the following annotation @RunWith(MyJUnitRunner.class)
. 我的
BaseTest
类使用以下注释@RunWith(MyJUnitRunner.class)
注释。
I've set up a Gradle task that is expected to run only SlowTests
. 我已经设置了一个Gradle任务,预计只运行
SlowTests
。 Here's my Gradle task: 这是我的Gradle任务:
task integrationTests(type: Test) {
minHeapSize = "768m"
maxHeapSize = "1024m"
testLogging {
events "passed", "skipped", "failed"
outputs.upToDateWhen {false}
}
reports.junitXml.destination = "$buildDir/test-result"
useJUnit {
includeCategories 'testutils.SlowTests'
}
}
When I run the task, my tests aren't run. 当我运行任务时,我的测试没有运行。 I've pinpointed this issue to be related to the custom runner
MyJUnitRunner
on the BaseTest
. 我已经精确定位这个问题进行相关的定制的运行
MyJUnitRunner
上BaseTest
。 How can I set up my Gradle or test structure so that I can use a custom runner while using the Suite
. 如何设置我的Gradle或测试结构,以便在使用
Suite
时可以使用自定义运行器。
The solution to this turned out to smaller and trickier than I thought. 对此的解决方案比我想象的更小,更棘手。 Gradle was using my custom test runner and correctly invoking the
filter
method. Gradle正在使用我的自定义测试运行
filter
并正确调用filter
方法。 However, my runner reloads all test classes through its own classloader for Javaassist enhancements. 但是,我的运行器通过自己的类加载器重新加载所有测试类以进行Javaassist增强。
This lead to the issue that SlowTest
annotation was loaded through the Gradle classloader but when passed to my custom runner, the runner checked if the class was annotated with that annotation. 这导致了通过Gradle类加载器加载
SlowTest
注释的问题,但是当传递给我的自定义运行器时,运行器检查该类是否使用该注释进行注释。 This check never resolved correctly as the equality of the SlowTest
annotation loaded through two different classloaders was different. 由于通过两个不同的类加载器加载的
SlowTest
注释的相等性不同,因此此检查永远无法正确解析。
-- -
Since I've already done the research, I'll just leave this here. 既然我已经完成了研究,我就把它放在这里。 After days of digging through the Gradle and the (cryptic) JUnit sources, here's what I got.
经过几天的Gradle和(神秘的)JUnit来源挖掘,这就是我得到的。
Gradle simply doesn't handle any advanced JUnit functionality except the test categorization. 除测试分类外,Gradle不会处理任何高级JUnit功能。 When you create a Gradle task with the include-categories or the exclude-categories conditions, it builds a CategoryFilter.
使用include-categories或exclude-categories条件创建Gradle任务时,它会构建一个CategoryFilter。 If you don't know, a
Filter
is what JUnit gives to the test-runner to decide whether a test or a test method should be filtered out. 如果您不知道,
Filter
是JUnit为测试运行Filter
提供的,以决定是否应该过滤掉测试或测试方法。 The test runner must implement the Filterable
interface. 测试运行器必须实现
Filterable
接口。
JUnit comes with multiple runners, the Categories
is just another one of them. JUnit带有多个运行器,
Categories
只是另一个。 It extends a family of test runners called Suite
. 它扩展了一系列名为
Suite
的测试跑步者。 These suite based runners are designed to run a "suite" of tests. 这些基于套件的跑步者设计用于运行“套件”测试。 A suite of tests could be built by annotation introspection, by explicitly defining tests in a suite or any other method that builds a suite of tests.
可以通过注释内省,通过在套件中显式定义测试或构建一组测试的任何其他方法来构建一套测试。
In the case of the Categories
runner, JUnit has it's own CategoryFilter
but Gradle doesn't use that, it uses it's own CategoryFilter
. 在
Categories
的情况下,JUnit拥有它自己的CategoryFilter
但Gradle不使用它,它使用它自己的CategoryFilter
。 Both provide more or less the same functionality and are JUnit filters so that can be used by any suite that implements Filterable
. 两者都提供或多或少相同的功能,并且是JUnit过滤器,因此任何实现
Filterable
套件都可以使用它们。
The actual class in the Gradle responsible for running the JUnit tests is called JUnitTestClassExecuter
. 负责运行JUnit测试的Gradle中的实际类称为
JUnitTestClassExecuter
。 Once it has parsed the command line options it requests JUnit to check the runner should be used for a test. 一旦解析了命令行选项,它就会请求JUnit检查跑步者是否应该用于测试。 This method is invoked for every test as seen here .
这种方法被调用每一个测试所看到这里 。
The rest is simply up to JUnit. 剩下的就是JUnit。 Gradle just created a custom
RunNotifier
to generate the standard XML files representing test results. Gradle刚刚创建了一个自定义
RunNotifier
来生成表示测试结果的标准XML文件。
I hope someone finds this useful and saved themselves countless hours of debugging. 我希望有人发现这很有用,并为自己节省了无数小时的调试时间。
TLDR: You can use any runner in Gradle. TLDR:您可以在Gradle中使用任何跑步者。 Gradle has no specifics pertaining to runners.
Gradle没有关于跑步者的细节。 It is JUnit that decided the runners.
是JUnit决定了跑步者。 If you'd like to know what runner will be used for your test, you can debug this by calling
Request.aClass(testClass).getRunner()
. 如果您想知道将使用哪个运行器进行测试,可以通过调用
Request.aClass(testClass).getRunner()
来调试它。 Hack this somewhere into your codebase and print it to the console. 将此内容隐藏到您的代码库中并将其打印到控制台。 (I wasn't very successful in attaching a debugger to Gradle.)
(我在将调试器附加到Gradle方面不是很成功。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.