8

我有一堆 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'
    }
}

当我运行任务时,我的测试没有运行。我已经确定这个问题MyJUnitRunnerBaseTest. 如何设置我的 Gradle 或测试结构,以便在使用Suite.

4

1 回答 1

6

解决这个问题的方法比我想象的要小和复杂。Gradle 正在使用我的自定义测试运行程序并正确调用该filter方法。但是,我的跑步者通过其自己的类加载器重新加载所有测试类以增强 Javaassist。

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

--

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

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

JUnit 带有多个运行器,这Categories只是其中一个。它扩展了一个名为Suite. 这些基于套件的运行器旨在运行“套件”测试。可以通过注释自省、在套件中显式定义测试或构建测试套件的任何其他方法来构建测试套件。

Categories跑步者的情况下,JUnit 有它自己的CategoryFilter,但 Gradle 不使用它,它使用它自己的CategoryFilter. 两者都提供或多或少相同的功能,并且都是 JUnit 过滤器,因此任何实现Filterable.

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

其余的完全取决于 JUnit。Gradle 刚刚创建了一个自定义RunNotifier来生成代表测试结果的标准 XML 文件。

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

TLDR:您可以在 Gradle 中使用任何运行程序。Gradle 没有关于跑步者的细节。决定跑步者的是 JUnit。如果您想知道您的测试将使用什么运行器,您可以通过调用 Request.aClass(testClass).getRunner(). 将其破解到您的代码库中并将其打印到控制台。(我在将调试器附加到 Gradle 方面并不是很成功。)

于 2016-10-31T15:34:07.710 回答