在Junit中使用类别时,如何使用自定义运行器?

时间:2016-10-28 08:07:24

标签: java unit-testing gradle junit junit-runner

我有一堆JUnit测试扩展了我的基础测试类BaseTest,后者又扩展了Assert。我的一些测试有一个@Category(SlowTests.class)注释。

我的BaseTest类使用以下注释@RunWith(MyJUnitRunner.class)进行注释。

我已经设置了一个Gradle任务,该任务只能运行SlowTests。这是我的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'
    }
}

当我运行任务时,我的测试没有运行。我已经确定此问题与MyJUnitRunner上的自定义转轮BaseTest有关。如何设置我的Gradle或测试结构,以便在使用Suite时可以使用自定义运行器。

1 个答案:

答案 0 :(得分:5)

对此的解决方案比我想象的更小,更棘手。 Gradle正在使用我的自定义测试运行器并正确调用filter方法。但是,我的运行器通过自己的类加载器重新加载所有测试类以进行Javaassist增强。

这导致SlowTest注释通过Gradle类加载器加载的问题,但是当传递给我的自定义运行器时,运行器检查该类是否使用该注释进行注释。此检查从未正确解决,因为通过两个不同的类加载器加载的SlowTest注释的相等性是不同的。

-

由于我已经完成了研究,我将把它留在这里。经过几天的Gradle和(神秘的)JUnit来源,这就是我得到的。

Gradle除了测试分类外,根本不处理任何高级JUnit功能。使用include-categories或exclude-categories条件创建Gradle任务时,它会构建一个CategoryFilter。如果你不知道,Filter是JUnit为测试运行者提供的,以决定是否应该过滤掉测试或测试方法。测试运行器必须实现Filterable接口。

JUnit带有多个跑步者,Categories只是其中一个。它扩展了一系列名为Suite的测试跑步者。这些基于套件的跑步者设计用于运行“套件”测试。可以通过注释内省,通过在套件中显式定义测试或构建一组测试的任何其他方法来构建一套测试。

对于Categories跑步者,JUnit拥有它自己的CategoryFilter,但Gradle不使用它,它使用它自己的CategoryFilter。两者都提供或多或少相同的功能,并且是JUnit过滤器,因此可以由任何实现Filterable的套件使用。

负责运行JUnit测试的Gradle中的实际类称为JUnitTestClassExecuter。一旦解析了命令行选项,它就会请求JUnit检查跑步者是否应该用于测试。每个测试都会调用此方法,如here所示。

剩下的就是JUnit。 Gradle刚刚创建了一个自定义RunNotifier来生成代表测试结果的标准XML文件。

我希望有人发现这很有用,并为自己节省了无数个小时的调试时间。

TLDR:您可以在Gradle中使用任何跑步者。 Gradle没有关于跑步者的细节。是JUnit决定了跑步者。如果您想知道哪个跑步者将用于您的测试,您可以通过调用来调试 Request.aClass(testClass).getRunner()。将此内容隐藏到您的代码库中并将其打印到控制台。 (我在将调试器附加到Gradle方面不是很成功。)