问题描述
我试图将我的测试区分为单元测试和集成测试。
我的想法是使用新的JUnit5 Annotation
关于如何将Spek和JUnit5标签或其他想法集成到单元测试和集成测试中的想法?
今天我跑完全一样的问题。我必须将测试分为3个部分:单元,服务(测试REST API)和集成(WebDriver)。
Disclamer:适用于任何测试框架,不仅适用于 Spek 。 Gradle 4.6 或更新版本才能运行。
将测试源集合分成源集在我的例子中,它们是:
- <$ c $
c> src / test - 对于单元测试(您已经拥有它)
- src / serviceTest - 用于服务测试
- src / integrationTest - 用于集成测试
所有这些集合都应该有标准的源集合结构。在您的项目中创建这些文件夹并将您的软件包移动到相应的源集。
完成后,在依赖部分 $ c $>以下行:
sourceSets {
integrationTest {
compileClasspath + = main.output
runtimeClasspath + = main.output
}
serviceTest {
compileClasspath + = main.output
runtimeClasspath + = main.output
}
}
配置{
integrationTestCompile.extendsFrom testCompile
integrationTestRuntime.extendsFrom testRuntime
serviceTestCompile.extendsFrom testCompile
serviceTestRuntime.extendsFrom testRuntime
}
执行此操作后,您的IDE(我想你使用Idea)应重新索引 build.gradle 并识别源集。您的新来源集可能有错误,因为他们没有看到其他来源。这是正确的,因为这些源集意在独立运行,而且不应该是一个问题。
将依赖关系分隔为适当的配置(可选)
缺省值 serviceTest 和 integrationTest 继承所有 test 依赖关系,但是如果您需要将某些特定配置移出通用范围,则可以在此处执行此操作。 在我的情况下, WebDriver 非常重,除了集成测试之外,我不需要它。
依赖关系{
//可用于所有作用域
testCompileorg.jetbrains.spek:spek- api:$ spekVersion
testRuntimeorg.jetbrains.spek:spek-junit-platform-engine:$ spekVersion
testCompileorg.junit.platform:junit-platform-launcher:$ junitPlatformVersion
//仅编译integrationTest
integrationTestCompileorg.seleniumhq.selenium:selenium-java:3.11.0
integrationTestCompileorg.seleniumhq.selenium.fluent:fluent-selenium :1.19
安装程序执行顺序
我们需要添加测试类型的gradle任务并设置它。您可以为不同的测试任务设置不同的设置。
task serviceTest(type:Test){
//运行测试从src / serviceTest
testClassesDirs = sourceSets.serviceTest.output.classesDirs
classpath = sourceSets.serviceTest.runtimeClasspath
}
//安装serviceTest任务
serviceTest {
//如果您需要在第一次失败后跳过集合中的测试,请取消注释。由于Gradle 4.6
// failFast = true
//启用某些日志记录
testLogging {
eventsPASSED,FAILED,SKIPPED
}
//启用JUnit5测试
useJUnitPlatform {
}
}
对integrationTest执行相同操作。
最后,设置依赖项和执行顺序:
//在gradle检查期间运行服务测试
check.dependsOn serviceTest
check.dependsOn integrationTest
//在单元测试后运行服务测试
serviceTest.mustRunAfter测试
//在服务测试后运行集成测试
integrationTest.mustRunAfter serviceTest
结论
您将获得:
- 的单位 - 单位 - >服务 - >集成测试套件以严格顺序运行;
- 如果测试失败(不管 failFast 选项),其余的将不会运行并浪费资源;
- 能够在执行 gradle< task>
其他资源:
- 以下是,它使用 Spek
- 介绍了很多与测试相关的内容。
I am trying to distinguish my tests into Unit- and Integration tests.My idea was to use the new JUnit5 Annotation @Tag("unit") which works nicely for my JUnit tests, but I cannot get it to work with Spek.
What I currently have is my class:
data class MyObject(val value: Int)
My tests:
@Tag("unit") object MyObjectTest { @Test fun checkEquality() { val o1 = MyObject(1) assertEquals(o1, o1) } }
With my build.gradle having:
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" } }
When I execute utest, this works.However when doing the same with Spek:
@Tag("unit") object MyObjectSpek : Spek({ given("an Object") { val o1 = MyObject(1) it("should be equal to itself") { assertEquals(o1, o1) } } })
What happens is if I run the gradle task utest it only executes the methods from MyObjectTest and does not execute the tests for MyObjectSpek
Any ideas on how to integrate Spek with JUnit5 Tags or another idea to seperate unit tests and integration tests?
today I ran exactly into the same problem. I had to separate tests into 3 sections: Unit, Service (testing REST API) and Integration (WebDriver).
Disclamer: this guide is applicable for any testing framework, not only to Spek. Gradle 4.6 or newer is required to run this.
Separate test source set into source sets
In my example they would be:
- src/test — for Unit tests (you already have it)
- src/serviceTest — for Service tests
- src/integrationTest — for Integration tests
all these sets should have standard source set structure. Create these folders inside your project and move your packages to corresponding source sets.
When it is done add to build.gradle before dependency section following lines:
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 }
After you do this your IDE (I suppose you use Idea) should reindex build.gradle and recognize source sets. You may have errors in your new source sets because they do not see each other sources. That's correct, because these source sets intended to run independently, and should not be a problem.
Separate dependencies to appropriate configurations (Optional)
By default serviceTest and integrationTest inherit all test dependencies, but if you need to move something specific to certain configuration out of common scope, you can do this here.
In my case WebDriver is quite heavy and I do not need it anywhere except integration testing.
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" }
Setup execution order
We will need to add gradle task of Test type and setup it. You can have different settings for different test tasks.
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 { } }
Do the same for integrationTest.
Finally, setup the dependencies and order of execution:
// 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
Conclusion
You will get:
- Chain of Unit -> Service -> Integration test suites running in strict order;
- If you will get a test failure (regardless of failFast option) in one test suite, the remaining won't run and waste resources;
- Ability to run from console each suite separately within execution of gradle <task>.
Additional resources:
- Here is the sample build.gradle that implements this setup with Spek
- Release notes of gradle 4.6 version introducing a lot of stuff related to testing.
这篇关于为Spek使用JUnit5标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!