jvm-test-suite通用测试源,用于多个测试套件中使用。

huangapple go评论44阅读模式
英文:

jvm-test-suite common test sources for use in multiple test suites

问题

使用jvm-test-suite Gradle插件,我希望能够创建一个通用的测试源集,以供其他测试套件使用。我设想的结构如下,common中的源代码和资源可以在unitintegrationfunctionalperformance中使用:

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(&quot;UnstableApiUsage&quot;)

plugins {
    `jvm-test-suite`
}

// Register `commonTest` source set
sourceSets {
    register(&quot;commonTest&quot;) {
        java {
            compileClasspath += named(&quot;main&quot;).get().output
            runtimeClasspath += named(&quot;main&quot;).get().output
            srcDir(&quot;src/test/common/kotlin&quot;)
        }
        resources {
            srcDir(&quot;src/test/common/resources&quot;)
        }
    }
}

// Make `commonTestImplementation` extend from `testImplementation` so that we can use all dependencies that `testImplementation` uses
val commonTestImplementation by configurations.getting {
    extendsFrom(configurations.named(&quot;testImplementation&quot;).get())
}

configure&lt;TestingExtension&gt; {
    suites {
        val sourceSetMain = sourceSets.named(&quot;main&quot;).get()
        val sourceSetCommon = sourceSets.named(&quot;commonTest&quot;).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(&quot;src/test/unit/kotlin&quot;))
                    // I&#39;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(&quot;src/test/unit/kotlin&quot;, sourceSetCommon.java.srcDirs))
                }
                resources {
                    setSrcDirs(listOf(&quot;src/test/unit/resources&quot;))
                    // setSrcDirs(listOf(&quot;src/test/unit/resources&quot;, 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(&quot;src/test/functional/kotlin&quot;))
                }
                resources {
                    setSrcDirs(listOf(&quot;src/test/functional/resources&quot;))
                }
            }

            targets {
                all {
                    testTask.configure {
                        shouldRunAfter(test)
                    }
                }
            }
        }
    }
}

val functionalTestImplementation by configurations.getting {
    extendsFrom(configurations.named(&quot;testImplementation&quot;).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&lt;JvmTestSuite&gt;(&quot;test&quot;) {
testType.set(&quot;common&quot;)
useJUnitJupiter()
sources {
kotlin {
setSrcDirs(listOf(&quot;src/test/common/kotlin&quot;))
}
resources {
setSrcDirs(listOf(&quot;src/test/common/resources&quot;))
}
}
dependencies {
// We can replace direct dependency on main&#39;s runtimeClasspath with implementation(project())
// once https://github.com/gradle/gradle/issues/25269 is resolved
implementation(sourceSets.main.get().runtimeClasspath)
}
}
register&lt;JvmTestSuite&gt;(&quot;unitTest&quot;) {
testType.set(UNIT_TEST)
useJUnitJupiter()
sources {
kotlin {
setSrcDirs(listOf(&quot;src/test/unitTest/kotlin&quot;))
}
resources {
setSrcDirs(listOf(&quot;src/test/unitTest/resources&quot;))
}
}
dependencies {
implementation(sourceSets.test.get().runtimeClasspath)
implementation(sourceSets.test.get().output)
}
}
register&lt;JvmTestSuite&gt;(&quot;integrationTest&quot;) {
testType.set(INTEGRATION_TEST)
useJUnitJupiter()
sources {
kotlin {
setSrcDirs(listOf(&quot;src/test/integrationTest/kotlin&quot;))
}
resources {
setSrcDirs(listOf(&quot;src/test/integrationTest/resources&quot;))
}
}
dependencies {
implementation(sourceSets.test.get().runtimeClasspath)
implementation(sourceSets.test.get().output)
}
}
register&lt;JvmTestSuite&gt;(&quot;acceptanceTest&quot;) {
testType.set(&quot;acceptance-test&quot;)
useJUnitJupiter()
sources {
kotlin {
setSrcDirs(listOf(&quot;src/test/acceptanceTest/kotlin&quot;))
}
resources {
setSrcDirs(listOf(&quot;src/test/acceptanceTest/resources&quot;))
}
}
dependencies {
implementation(sourceSets.test.get().runtimeClasspath)
implementation(sourceSets.test.get().output)
}
}
}
}
tasks.named(&quot;check&quot;) {
dependsOn(
testing.suites.named(&quot;unitTest&quot;),
testing.suites.named(&quot;integrationTest&quot;),
testing.suites.named(&quot;acceptanceTest&quot;)
)
}

<!-- 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(&quot;src/test/$dirName/kotlin&quot;))
resources.setSrcDirs(listOf(&quot;src/test/$dirName/resources&quot;))
}
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(&quot;common&quot;)
}
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(&quot;unit&quot;)
}
val functionalTest by registering(JvmTestSuite::class) {
testType.set(TestSuiteType.FUNCTIONAL_TEST)
sources.configureSrcSetDirs(&quot;functional&quot;)
shouldRunAfter(test)
}
val integrationTest by registering(JvmTestSuite::class) {
testType.set(TestSuiteType.INTEGRATION_TEST)
sources.configureSrcSetDirs(&quot;integration&quot;)
shouldRunAfter(functionalTest)
}
register&lt;JvmTestSuite&gt;(&quot;performanceTest&quot;) {
testType.set(TestSuiteType.PERFORMANCE_TEST)
sources.configureSrcSetDirs(&quot;performance&quot;)
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(&quot;check&quot;) {
// already depends on &quot;test&quot;
dependsOn(testing.suites.named(&quot;functionalTest&quot;))
dependsOn(testing.suites.named(&quot;integrationTest&quot;))
dependsOn(testing.suites.named(&quot;performanceTest&quot;))
}

huangapple
  • 本文由 发表于 2023年2月7日 00:45:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75364196.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定