英文:
jvm-test-suite common test sources for use in multiple test suites
问题
使用jvm-test-suite
Gradle插件,我希望能够创建一个通用的测试源集,以供其他测试套件使用。我设想的结构如下,common
中的源代码和资源可以在unit
、integration
、functional
和performance
中使用:
project/
├─ src/
│ ├─ main/
│ ├─ test/
│ │ ├─ common/
│ │ │ ├─ kotlin/
│ │ │ ├─ resources/
│ ├─ unit/
│ │ ├─ kotlin/
│ │ ├─ resources/
│ ├─ integration/
│ │ ├─ kotlin/
│ │ ├─ resources/
│ ├─ functional/
│ │ ├─ kotlin/
│ │ ├─ resources/
│ ├─ performance/
│ │ ├─ kotlin/
│ │ ├─ resources/
到目前为止,我尝试了以下方法,我认为这应该为每个测试套件提供适当的类路径:
@file:Suppress("UnstableApiUsage")
plugins {
`jvm-test-suite`
}
// 注册 `commonTest` 源集
sourceSets {
register("commonTest") {
java {
compileClasspath += named("main").get().output
runtimeClasspath += named("main").get().output
srcDir("src/test/common/kotlin")
}
resources {
srcDir("src/test/common/resources")
}
}
}
// 使 `commonTestImplementation` 扩展自 `testImplementation`,以便我们可以使用 `testImplementation` 使用的所有依赖项
val commonTestImplementation by configurations.getting {
extendsFrom(configurations.named("testImplementation").get())
}
configure<TestingExtension> {
suites {
val sourceSetMain = sourceSets.named("main").get()
val sourceSetCommon = sourceSets.named("commonTest").get()
// 这些可能只是变量,而不是延迟评估
val sourceSetMainClasspath = { sourceSetMain.compileClasspath + sourceSetMain.output }
val sourceSetCommonClasspath = { sourceSetMain.compileClasspath + sourceSetMain.output }
val test by getting(JvmTestSuite::class) {
testType.set(TestSuiteType.UNIT_TEST)
sources {
// 将通用测试编译类路径和输出添加到 `unitTest` 套件中?
compileClasspath += sourceSetCommonClasspath()
runtimeClasspath += output + compileClasspath
java {
setSrcDirs(listOf("src/test/unit/kotlin"))
}
resources {
setSrcDirs(listOf("src/test/unit/resources"))
}
}
}
val functionalTest by registering(JvmTestSuite::class) {
testType.set(TestSuiteType.FUNCTIONAL_TEST)
dependencies {
implementation(project())
}
sources {
// 将通用测试编译类路径和输出添加到 `unitTest` 套件中?
compileClasspath += sourceSetCommonClasspath()
runtimeClasspath += output + compileClasspath
java {
setSrcDirs(listOf("src/test/functional/kotlin"))
}
resources {
setSrcDirs(listOf("src/test/functional/resources"))
}
}
targets {
all {
testTask.configure {
shouldRunAfter(test)
}
}
}
}
}
}
val functionalTestImplementation by configurations.getting {
extendsFrom(configurations.named("testImplementation").get())
}
从这个代码中,我期望能够在单元测试(unit
)目录和功能测试(functional
)目录中访问通用测试源。然而,这并没有按预期工作。非常感谢您的任何想法和意见!
英文:
Using the jvm-test-suite
gradle plugin, I would like to be able to create a common test source set for use in other test suites. I envision the structure to look like the following where the sources and resources from common
can be used in unit
, integration
, functional
, and performance
:
project/
├─ src/
│ ├─ main/
│ ├─ test/
│ │ ├─ common/
│ │ │ ├─ kotlin/
│ │ │ ├─ resources/
│ │ ├─ unit/
│ │ │ ├─ kotlin/
│ │ │ ├─ resources/
│ │ ├─ integration/
│ │ │ ├─ kotlin/
│ │ │ ├─ resources/
│ │ ├─ functional/
│ │ │ ├─ kotlin/
│ │ │ ├─ resources/
│ │ ├─ performance/
│ │ │ ├─ kotlin/
│ │ │ ├─ resources/
So far I have tried the following, which I thought would provide the proper classpaths for each test suite:
@file:Suppress("UnstableApiUsage")
plugins {
`jvm-test-suite`
}
// Register `commonTest` source set
sourceSets {
register("commonTest") {
java {
compileClasspath += named("main").get().output
runtimeClasspath += named("main").get().output
srcDir("src/test/common/kotlin")
}
resources {
srcDir("src/test/common/resources")
}
}
}
// Make `commonTestImplementation` extend from `testImplementation` so that we can use all dependencies that `testImplementation` uses
val commonTestImplementation by configurations.getting {
extendsFrom(configurations.named("testImplementation").get())
}
configure<TestingExtension> {
suites {
val sourceSetMain = sourceSets.named("main").get()
val sourceSetCommon = sourceSets.named("commonTest").get()
// These might be able to just be variables instead of lazy evaluation
val sourceSetMainClasspath = { sourceSetMain.compileClasspath + sourceSetMain.output }
val sourceSetCommonClasspath = { sourceSetMain.compileClasspath + sourceSetMain.output }
val test by getting(JvmTestSuite::class) {
testType.set(TestSuiteType.UNIT_TEST)
sources {
// Add common test compile classpath and outputs to the `unitTest` suite?
compileClasspath += sourceSetCommonClasspath()
runtimeClasspath += output + compileClasspath
java {
setSrcDirs(listOf("src/test/unit/kotlin"))
// I've also tried the following which only works when applied to only 1 test suite but not all. Same with the commented out resources portion directly below
// setSrcDirs(listOf("src/test/unit/kotlin", sourceSetCommon.java.srcDirs))
}
resources {
setSrcDirs(listOf("src/test/unit/resources"))
// setSrcDirs(listOf("src/test/unit/resources", sourceSetCommon.resources.srcDirs))
}
}
}
val functionalTest by registering(JvmTestSuite::class) {
testType.set(TestSuiteType.FUNCTIONAL_TEST)
dependencies {
implementation(project())
}
sources {
// Add common test compile classpath and outputs to the `unitTest` suite?
compileClasspath += sourceSetCommonClasspath()
runtimeClasspath += output + compileClasspath
java {
setSrcDirs(listOf("src/test/functional/kotlin"))
}
resources {
setSrcDirs(listOf("src/test/functional/resources"))
}
}
targets {
all {
testTask.configure {
shouldRunAfter(test)
}
}
}
}
}
}
val functionalTestImplementation by configurations.getting {
extendsFrom(configurations.named("testImplementation").get())
}
From this, I expect to be able to access common test sources in both the unit test (unit
) directory and functional test (functional
) directory. However, this does not work as expected. Any thoughts/input are greatly appreciated!
答案1
得分: 0
也许我的解决方案可以帮助你。
我的测试结构如下:
src/test/common
src/test/unitTest
src/test/integrationTest
src/test/acceptanceTest
实际上,我只是将默认的 test
源集调整为 common
,将其源代码从 src/test
移动到 src/test/common
,并使其他测试源集依赖于它。
以下是使其工作所需的全部内容(使用 Kotlin 编写):
plugins {
`jvm-test-suite`
}
testing {
suites {
getByName<JvmTestSuite>("test") {
testType.set("common")
useJUnitJupiter()
sources {
kotlin {
setSrcDirs(listOf("src/test/common/kotlin"))
}
resources {
setSrcDirs(listOf("src/test/common/resources"))
}
}
dependencies {
// 一旦 https://github.com/gradle/gradle/issues/25269 得到解决,我们可以用 implementation(project()) 替代对 main 的 runtimeClasspath 的直接依赖
implementation(sourceSets.main.get().runtimeClasspath)
}
}
register<JvmTestSuite>("unitTest") {
testType.set(UNIT_TEST)
useJUnitJupiter()
sources {
kotlin {
setSrcDirs(listOf("src/test/unitTest/kotlin"))
}
resources {
setSrcDirs(listOf("src/test/unitTest/resources"))
}
}
dependencies {
implementation(sourceSets.test.get().runtimeClasspath)
implementation(sourceSets.test.get().output)
}
}
register<JvmTestSuite>("integrationTest") {
testType.set(INTEGRATION_TEST)
useJUnitJupiter()
sources {
kotlin {
setSrcDirs(listOf("src/test/integrationTest/kotlin"))
}
resources {
setSrcDirs(listOf("src/test/integrationTest/resources"))
}
}
dependencies {
implementation(sourceSets.test.get().runtimeClasspath)
implementation(sourceSets.test.get().output)
}
}
register<JvmTestSuite>("acceptanceTest") {
testType.set("acceptance-test")
useJUnitJupiter()
sources {
kotlin {
setSrcDirs(listOf("src/test/acceptanceTest/kotlin"))
}
resources {
setSrcDirs(listOf("src/test/acceptanceTest/resources"))
}
}
dependencies {
implementation(sourceSets.test.get().runtimeClasspath)
implementation(sourceSets.test.get().output)
}
}
}
}
tasks.named("check") {
dependsOn(
testing.suites.named("unitTest"),
testing.suites.named("integrationTest"),
testing.suites.named("acceptanceTest")
)
}
希望这可以帮助你。
英文:
Maybe my solution could help you.
My test structure is as follows:
src/test/common
src/test/unitTest
src/test/integrationTest
src/test/acceptanceTest
In fact, I only adjusted the default test
source set to become common
, moved its sources from src/test
to src/test/common
, and made the other test source sets dependent on it.
Here is all you need to make it working (in Kotlin):
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-kotlin -->
plugins {
`jvm-test-suite`
}
testing {
suites {
getByName<JvmTestSuite>("test") {
testType.set("common")
useJUnitJupiter()
sources {
kotlin {
setSrcDirs(listOf("src/test/common/kotlin"))
}
resources {
setSrcDirs(listOf("src/test/common/resources"))
}
}
dependencies {
// We can replace direct dependency on main's runtimeClasspath with implementation(project())
// once https://github.com/gradle/gradle/issues/25269 is resolved
implementation(sourceSets.main.get().runtimeClasspath)
}
}
register<JvmTestSuite>("unitTest") {
testType.set(UNIT_TEST)
useJUnitJupiter()
sources {
kotlin {
setSrcDirs(listOf("src/test/unitTest/kotlin"))
}
resources {
setSrcDirs(listOf("src/test/unitTest/resources"))
}
}
dependencies {
implementation(sourceSets.test.get().runtimeClasspath)
implementation(sourceSets.test.get().output)
}
}
register<JvmTestSuite>("integrationTest") {
testType.set(INTEGRATION_TEST)
useJUnitJupiter()
sources {
kotlin {
setSrcDirs(listOf("src/test/integrationTest/kotlin"))
}
resources {
setSrcDirs(listOf("src/test/integrationTest/resources"))
}
}
dependencies {
implementation(sourceSets.test.get().runtimeClasspath)
implementation(sourceSets.test.get().output)
}
}
register<JvmTestSuite>("acceptanceTest") {
testType.set("acceptance-test")
useJUnitJupiter()
sources {
kotlin {
setSrcDirs(listOf("src/test/acceptanceTest/kotlin"))
}
resources {
setSrcDirs(listOf("src/test/acceptanceTest/resources"))
}
}
dependencies {
implementation(sourceSets.test.get().runtimeClasspath)
implementation(sourceSets.test.get().output)
}
}
}
}
tasks.named("check") {
dependsOn(
testing.suites.named("unitTest"),
testing.suites.named("integrationTest"),
testing.suites.named("acceptanceTest")
)
}
<!-- end snippet -->
答案2
得分: 0
在这种情况下,我创建了一个名为 commonTest
的新源集。然后,对于每个 JvmTestSuite
类型,我将项目和 commonTest
的输出添加为依赖项。由于我在顶部添加了扩展方法,这使得为每个测试集以及任何未来的测试集添加配置变得非常容易。
plugins {
`jvm-test-suite`
}
fun SourceSet.configureSrcSetDirs(dirName: String) {
java.setSrcDirs(listOf("src/test/$dirName/kotlin"))
resources.setSrcDirs(listOf("src/test/$dirName/resources"))
}
fun JvmTestSuite.shouldRunAfter(vararg paths: Any) =
targets.all {
testTask.configure {
shouldRunAfter(paths)
}
}
fun SourceSet.addSrcSetMainClasspath() {
compileClasspath += sourceSets.main.get().compileClasspath + sourceSets.main.get().output
runtimeClasspath += output + compileClasspath
}
val commonTest: SourceSet by sourceSets.creating {
addSrcSetMainClasspath()
configureSrcSetDirs("common")
}
testing {
suites {
configureEach {
if (this is JvmTestSuite) {
dependencies {
implementation(project(path))
implementation(commonTest.output)
}
sources.addSrcSetMainClasspath()
}
}
val test by getting(JvmTestSuite::class) {
testType.set(TestSuiteType.UNIT_TEST)
sources.configureSrcSetDirs("unit")
}
val functionalTest by registering(JvmTestSuite::class) {
testType.set(TestSuiteType.FUNCTIONAL_TEST)
sources.configureSrcSetDirs("functional")
shouldRunAfter(test)
}
val integrationTest by registering(JvmTestSuite::class) {
testType.set(TestSuiteType.INTEGRATION_TEST)
sources.configureSrcSetDirs("integration")
shouldRunAfter(functionalTest)
}
register<JvmTestSuite>("performanceTest") {
testType.set(TestSuiteType.PERFORMANCE_TEST)
sources.configureSrcSetDirs("performance")
shouldRunAfter(integrationTest)
}
}
}
val testImplementation: Configuration by configurations.getting
val integrationTestImplementation: Configuration by configurations.getting {
extendsFrom(testImplementation)
}
val functionalTestImplementation: Configuration by configurations.getting {
extendsFrom(testImplementation)
}
val performanceTestImplementation: Configuration by configurations.getting {
extendsFrom(testImplementation)
}
tasks.named("check") {
// already depends on "test"
dependsOn(testing.suites.named("functionalTest"))
dependsOn(testing.suites.named("integrationTest"))
dependsOn(testing.suites.named("performanceTest"))
}
希望这有所帮助!如果您需要进一步的解释或有其他问题,请随时提出。
英文:
I ended up with a much simpler solution which you can see below.
In this case, I create a new source set called commonTest
. Then for each JvmTestSuite type, I add as a dependency: the project and commonTest
's output. Since I added the extension methods at the top, this makes configuration for each test set, and any future ones, extremely easy to add.
plugins {
`jvm-test-suite`
}
fun SourceSet.configureSrcSetDirs(dirName: String) {
java.setSrcDirs(listOf("src/test/$dirName/kotlin"))
resources.setSrcDirs(listOf("src/test/$dirName/resources"))
}
fun JvmTestSuite.shouldRunAfter(vararg paths: Any) =
targets.all {
testTask.configure {
shouldRunAfter(paths)
}
}
fun SourceSet.addSrcSetMainClasspath() {
compileClasspath += sourceSets.main.get().compileClasspath + sourceSets.main.get().output
runtimeClasspath += output + compileClasspath
}
val commonTest: SourceSet by sourceSets.creating {
addSrcSetMainClasspath()
configureSrcSetDirs("common")
}
testing {
suites {
configureEach {
if (this is JvmTestSuite) {
dependencies {
implementation(project(path))
implementation(commonTest.output)
}
sources.addSrcSetMainClasspath()
}
}
val test by getting(JvmTestSuite::class) {
testType.set(TestSuiteType.UNIT_TEST)
sources.configureSrcSetDirs("unit")
}
val functionalTest by registering(JvmTestSuite::class) {
testType.set(TestSuiteType.FUNCTIONAL_TEST)
sources.configureSrcSetDirs("functional")
shouldRunAfter(test)
}
val integrationTest by registering(JvmTestSuite::class) {
testType.set(TestSuiteType.INTEGRATION_TEST)
sources.configureSrcSetDirs("integration")
shouldRunAfter(functionalTest)
}
register<JvmTestSuite>("performanceTest") {
testType.set(TestSuiteType.PERFORMANCE_TEST)
sources.configureSrcSetDirs("performance")
shouldRunAfter(integrationTest)
}
}
}
val testImplementation: Configuration by configurations.getting
val integrationTestImplementation: Configuration by configurations.getting {
extendsFrom(testImplementation)
}
val functionalTestImplementation: Configuration by configurations.getting {
extendsFrom(testImplementation)
}
val performanceTestImplementation: Configuration by configurations.getting {
extendsFrom(testImplementation)
}
tasks.named("check") {
// already depends on "test"
dependsOn(testing.suites.named("functionalTest"))
dependsOn(testing.suites.named("integrationTest"))
dependsOn(testing.suites.named("performanceTest"))
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论