如何在Gradle中使用JUnit平台拥有两组测试

4

我正在使用Gradle通过JUnit 5平台。

我的当前构建文件具有配置条款:

junitPlatform {
    platformVersion '1.0.0-M5'
    logManager 'java.util.logging.LogManager'
    enableStandardTestTask true

    filters {
        tags {
            exclude 'integration-test'
        }
        packages {
            include 'com.scherule.calendaring'
        }
    }
}

那很好。但我还需要运行集成测试,这需要构建应用程序,将其放入Docker并在后台运行。所以我需要第二个配置,仅在这种情况下才会启动...如何实现呢?通常我会扩展Test任务创建IntegrationTest任务,但它不适用于JUnit平台,因为没有简单的任务可以运行测试... 我知道我可以像这样做:
task integrationTests(dependsOn: "startMyAppContainer") {
    doLast {
        def request = LauncherDiscoveryRequestBuilder.request()
                .selectors(selectPackage("com.scherule.calendaring"))
                .filters(includeClassNamePatterns(".*IntegrationTest"))
                .build()

        def launcher = LauncherFactory.create()

        def listener = new SummaryGeneratingListener()
        launcher.registerTestExecutionListeners(listener)
        launcher.execute(request)
    }

    finalizedBy(stopMyAppContainer)
}

但是有没有更简单、更一致的方法呢?


Maven 能够根据类名区分单元测试和集成测试。请参考 http://maven.apache.org/surefire/maven-failsafe-plugin/ 中的讨论。我不熟悉 Gradle,但我相信它一定有类似的机制。 - SiKing
1个回答

10

目前在使用JUnit5插件的Gradle中,该功能还不完全支持(尽管它一直在逐步接近)。有几个解决方法。以下是我使用的方法:有点啰嗦,但它和Maven的测试与验证做的是同样的事情。

区分单元测试和集成测试类。

Gradle的主要和测试sourceSets很好用。添加一个新的integrationTest sourceSet,只描述你的集成测试。你可以使用文件名,但这可能意味着你需要调整测试sourceSet以跳过它当前包含的文件(在你的例子中,你希望从测试sourceSet中删除“.*IntegrationTest”,并仅在integrationTest sourceSet中留下它)。所以我更喜欢使用与测试sourceSet不同的根目录名称。

sourceSets {
  integrationTest {
    java {
      compileClasspath += main.output + test.output
      runtimeClasspath += main.output + test.output
      srcDir file('src/integrationTest/java')
    }
    resources.srcDir file('src/integrationTest/resources')
  }
}

由于我们有Java插件,这非常方便地创建了integrationTestCompileintegrationTestRuntime函数,可在dependencies块中使用:

dependencies {
    // .. other stuff snipped out ..
    testCompile "org.assertj:assertj-core:${assertjVersion}"

    integrationTestCompile("org.springframework.boot:spring-boot-starter-test") {
        exclude module: 'junit:junit'
    }
}

不错!

将集成测试添加到构建过程的正确位置

正如你所指出的那样,你确实需要一个运行集成测试的任务。你可以像你的示例中一样使用启动器;我只是委派给现有的控制台运行器,以利用简单的命令行选项。

def integrationTest = task('integrationTest',
                           type: JavaExec,
                           group: 'Verification') {
    description = 'Runs integration tests.'
    dependsOn testClasses
    shouldRunAfter test
    classpath = sourceSets.integrationTest.runtimeClasspath

    main = 'org.junit.platform.console.ConsoleLauncher'
    args = ['--scan-class-path',
            sourceSets.integrationTest.output.classesDir.absolutePath,
            '--reports-dir', "${buildDir}/test-results/junit-integrationTest"]
}

任务定义包含dependsOn和shouldRunAfter,以确保在运行集成测试时先运行单元测试。要确保当您运行 ./gradlew check 时运行集成测试,您需要更新check任务:

check {
  dependsOn integrationTest
}

现在你可以像使用./mvnw test一样使用./gradlew test,并且可以像使用./mvnw verify一样使用./gradlew check


这非常好和干净,谢谢先生!如果有人想知道是否将您的应用程序docker化,最好使用完全相同的容器来运行使用https://github.com/bmuschko/gradle-docker-plugin进行集成测试。然后,您可以在测试后轻松启动和停止容器。问题仍然是如何分配来自临时范围的第一个空闲端口...有人知道吗? - kboom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接