为 Spek 使用 JUnit5 标签
Use JUnit5 Tags for Spek
我试图将我的测试区分为单元测试和集成测试。
我的想法是使用新的 JUnit5 Annotation @Tag("unit")
,它非常适合我的 JUnit 测试,但我无法让它与 Spek 一起工作。
我目前拥有的是我的 class:
data class MyObject(val value: Int)
我的测试:
@Tag("unit")
object MyObjectTest {
@Test
fun checkEquality() {
val o1 = MyObject(1)
assertEquals(o1, o1)
}
}
我的 build.gradle 有:
task utest(type: Test) {
outputs.upToDateWhen { false }
useJUnitPlatform {
includeEngines 'junit-jupiter', 'junit-vintage', 'spek'
includeTags 'unit'
excludeTags 'performance', 'integration', 'functional'
}
testLogging {
events "passed", "skipped", "failed"
}
}
当我执行 utest 时,这有效。
然而,当用 Spek 做同样的事情时:
@Tag("unit")
object MyObjectSpek : Spek({
given("an Object") {
val o1 = MyObject(1)
it("should be equal to itself") {
assertEquals(o1, o1)
}
}
})
如果我 运行 gradle 任务测试它只执行 MyObjectTest
的方法而不执行 MyObjectSpek
[=17= 的测试,会发生什么]
关于如何将 Spek 与 JUnit5 标签集成的任何想法或分离单元测试和集成测试的其他想法?
今天我 运行 遇到了完全相同的问题。我不得不将测试分为 3 个部分:单元、服务(测试 REST API)和集成(WebDriver)。
免责声明: 本指南适用于任何测试框架,而不仅仅是 Spek
。 Gradle 4.6
或更新版本需要 运行 这个。
将测试源集分成源集
在我的示例中,它们将是:
src/test
— 用于单元测试(你已经有了)
src/serviceTest
— 用于服务测试
src/integrationTest
— 用于集成测试
所有这些集都应该有标准的源集结构。在您的项目中创建这些文件夹并将您的包移动到相应的源集。
完成后在 dependency section
之前添加到 build.gradle
以下行:
sourceSets {
integrationTest {
compileClasspath += main.output
runtimeClasspath += main.output
}
serviceTest {
compileClasspath += main.output
runtimeClasspath += main.output
}
}
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
serviceTestCompile.extendsFrom testCompile
serviceTestRuntime.extendsFrom testRuntime
}
执行此操作后,您的 IDE(我想您使用的是 Idea)应该重新索引 build.gradle
并识别源集。您的新源集中可能有错误,因为它们看不到彼此的源。这是正确的,因为这些源集旨在 运行 独立,应该不是问题。
将 dependencies
分隔为适当的配置(可选)
默认情况下 serviceTest
和 integrationTest
继承所有 test
依赖项,但如果您需要将某些特定于特定配置的内容移出通用范围,您可以在此处执行此操作。
在我的例子中,WebDriver
非常重,除了集成测试,我不需要它。
dependencies {
// available for all scopes
testCompile "org.jetbrains.spek:spek-api:$spekVersion"
testRuntime "org.jetbrains.spek:spek-junit-platform-engine:$spekVersion"
testCompile "org.junit.platform:junit-platform-launcher:$junitPlatformVersion"
// compiles only for integrationTest
integrationTestCompile "org.seleniumhq.selenium:selenium-java:3.11.0"
integrationTestCompile "org.seleniumhq.selenium.fluent:fluent-selenium:1.19"
}
设置执行顺序
我们需要添加 gradle 测试类型的任务并进行设置。不同的测试任务可以有不同的设置。
task serviceTest(type: Test) {
// Runs tests from src/serviceTest
testClassesDirs = sourceSets.serviceTest.output.classesDirs
classpath = sourceSets.serviceTest.runtimeClasspath
}
// Setup serviceTest task
serviceTest {
// Uncomment this if you need to skip tests from the set after first failure. Since Gradle 4.6
//failFast = true
// Enable some logging
testLogging {
events "PASSED", "FAILED", "SKIPPED"
}
// Enable JUnit5 tests
useJUnitPlatform {
}
}
对集成测试执行相同的操作。
最后,设置依赖关系和执行顺序:
// Make service tests run during gradle check
check.dependsOn serviceTest
check.dependsOn integrationTest
// Make service tests run after unit tests
serviceTest.mustRunAfter test
// Make integration tests run after service tests
integrationTest.mustRunAfter serviceTest
结论
您将获得:
-
Unit -> Service -> Integration
测试套件链 运行 严格按顺序排列;
- 如果您将在一个测试套件中获得测试失败(无论
failFast
选项如何),其余的将不会 运行 并浪费资源;
- 能够 运行 在
gradle <task>
的执行期间分别从控制台每个套件。
其他资源:
- 这里是 the sample
build.gradle
,它使用 Spek
实现了这个设置
- Release notes of gradle 4.6 版本引入了很多与测试相关的内容。
使用 IntelliJ 时需要考虑的另一件事是它对新源集有依赖性问题,请将其添加到您的 build.gradle:
apply plugin: 'idea'
idea {
module {
testSourceDirs += project.sourceSets.unitTest.kotlin.srcDirs
testSourceDirs += project.sourceSets.unitTest.resources.srcDirs
testSourceDirs += project.sourceSets.integrationTest.kotlin.srcDirs
testSourceDirs += project.sourceSets.integrationTest.resources.srcDirs
testSourceDirs += project.sourceSets.functionalTest.kotlin.srcDirs
testSourceDirs += project.sourceSets.functionalTest.resources.srcDirs
}
}
我试图将我的测试区分为单元测试和集成测试。
我的想法是使用新的 JUnit5 Annotation @Tag("unit")
,它非常适合我的 JUnit 测试,但我无法让它与 Spek 一起工作。
我目前拥有的是我的 class:
data class MyObject(val value: Int)
我的测试:
@Tag("unit")
object MyObjectTest {
@Test
fun checkEquality() {
val o1 = MyObject(1)
assertEquals(o1, o1)
}
}
我的 build.gradle 有:
task utest(type: Test) {
outputs.upToDateWhen { false }
useJUnitPlatform {
includeEngines 'junit-jupiter', 'junit-vintage', 'spek'
includeTags 'unit'
excludeTags 'performance', 'integration', 'functional'
}
testLogging {
events "passed", "skipped", "failed"
}
}
当我执行 utest 时,这有效。 然而,当用 Spek 做同样的事情时:
@Tag("unit")
object MyObjectSpek : Spek({
given("an Object") {
val o1 = MyObject(1)
it("should be equal to itself") {
assertEquals(o1, o1)
}
}
})
如果我 运行 gradle 任务测试它只执行 MyObjectTest
的方法而不执行 MyObjectSpek
[=17= 的测试,会发生什么]
关于如何将 Spek 与 JUnit5 标签集成的任何想法或分离单元测试和集成测试的其他想法?
今天我 运行 遇到了完全相同的问题。我不得不将测试分为 3 个部分:单元、服务(测试 REST API)和集成(WebDriver)。
免责声明: 本指南适用于任何测试框架,而不仅仅是 Spek
。 Gradle 4.6
或更新版本需要 运行 这个。
将测试源集分成源集
在我的示例中,它们将是:
src/test
— 用于单元测试(你已经有了)src/serviceTest
— 用于服务测试src/integrationTest
— 用于集成测试
所有这些集都应该有标准的源集结构。在您的项目中创建这些文件夹并将您的包移动到相应的源集。
完成后在 dependency section
之前添加到 build.gradle
以下行:
sourceSets {
integrationTest {
compileClasspath += main.output
runtimeClasspath += main.output
}
serviceTest {
compileClasspath += main.output
runtimeClasspath += main.output
}
}
configurations {
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
serviceTestCompile.extendsFrom testCompile
serviceTestRuntime.extendsFrom testRuntime
}
执行此操作后,您的 IDE(我想您使用的是 Idea)应该重新索引 build.gradle
并识别源集。您的新源集中可能有错误,因为它们看不到彼此的源。这是正确的,因为这些源集旨在 运行 独立,应该不是问题。
将 dependencies
分隔为适当的配置(可选)
默认情况下 serviceTest
和 integrationTest
继承所有 test
依赖项,但如果您需要将某些特定于特定配置的内容移出通用范围,您可以在此处执行此操作。
在我的例子中,WebDriver
非常重,除了集成测试,我不需要它。
dependencies {
// available for all scopes
testCompile "org.jetbrains.spek:spek-api:$spekVersion"
testRuntime "org.jetbrains.spek:spek-junit-platform-engine:$spekVersion"
testCompile "org.junit.platform:junit-platform-launcher:$junitPlatformVersion"
// compiles only for integrationTest
integrationTestCompile "org.seleniumhq.selenium:selenium-java:3.11.0"
integrationTestCompile "org.seleniumhq.selenium.fluent:fluent-selenium:1.19"
}
设置执行顺序
我们需要添加 gradle 测试类型的任务并进行设置。不同的测试任务可以有不同的设置。
task serviceTest(type: Test) {
// Runs tests from src/serviceTest
testClassesDirs = sourceSets.serviceTest.output.classesDirs
classpath = sourceSets.serviceTest.runtimeClasspath
}
// Setup serviceTest task
serviceTest {
// Uncomment this if you need to skip tests from the set after first failure. Since Gradle 4.6
//failFast = true
// Enable some logging
testLogging {
events "PASSED", "FAILED", "SKIPPED"
}
// Enable JUnit5 tests
useJUnitPlatform {
}
}
对集成测试执行相同的操作。
最后,设置依赖关系和执行顺序:
// Make service tests run during gradle check
check.dependsOn serviceTest
check.dependsOn integrationTest
// Make service tests run after unit tests
serviceTest.mustRunAfter test
// Make integration tests run after service tests
integrationTest.mustRunAfter serviceTest
结论
您将获得:
-
Unit -> Service -> Integration
测试套件链 运行 严格按顺序排列; - 如果您将在一个测试套件中获得测试失败(无论
failFast
选项如何),其余的将不会 运行 并浪费资源; - 能够 运行 在
gradle <task>
的执行期间分别从控制台每个套件。
其他资源:
- 这里是 the sample
build.gradle
,它使用Spek
实现了这个设置
- Release notes of gradle 4.6 版本引入了很多与测试相关的内容。
使用 IntelliJ 时需要考虑的另一件事是它对新源集有依赖性问题,请将其添加到您的 build.gradle:
apply plugin: 'idea'
idea {
module {
testSourceDirs += project.sourceSets.unitTest.kotlin.srcDirs
testSourceDirs += project.sourceSets.unitTest.resources.srcDirs
testSourceDirs += project.sourceSets.integrationTest.kotlin.srcDirs
testSourceDirs += project.sourceSets.integrationTest.resources.srcDirs
testSourceDirs += project.sourceSets.functionalTest.kotlin.srcDirs
testSourceDirs += project.sourceSets.functionalTest.resources.srcDirs
}
}