Skip to content

Commit

Permalink
refactor: use testkit library to test plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
mirko-felice authored and DanySK committed Jun 28, 2023
1 parent b095ddc commit d376bec
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 231 deletions.
17 changes: 16 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,25 @@ dependencies {
api(libs.nexus.publish)
implementation(libs.kotlinx.coroutines)
implementation(libs.fuel)
testImplementation(gradleTestKit())
testImplementation(libs.testkit)
testImplementation(libs.bundles.kotlin.testing)
}

/*
Following lines from 59-66 are needed as a workaround because of an official Gradle issue,
linked to https://github.com/gradle/gradle/issues/16603.
The issue is related to Gradle Daemon that is closed automatically by the Testkit official library,
but jacoco agent does not wait for it.
*/
inline fun <reified T : Task> Project.disableTrackState() {
tasks.withType<T>().configureEach {
doNotTrackState("Otherwise JaCoCo does not work correctly")
}
}

disableTrackState<Test>()
disableTrackState<JacocoReport>()

tasks.withType<KotlinCompile> {
kotlinOptions {
allWarningsAsErrors = true
Expand Down
5 changes: 3 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ dokka = "1.8.20"
kotest = "5.6.2"
kotlin = "1.8.22"
nexus-publish = "1.3.0"
testkit = "0.8.4"

[libraries]
fuel = "com.github.kittinunf.fuel:fuel:2.3.1"
konf-yaml = "com.uchuhimo:konf-yaml:1.1.2"
kotest-junit5-jvm = { module = "io.kotest:kotest-runner-junit5-jvm", version.ref = "kotest" }
kotest-assertions-core-jvm = { module = "io.kotest:kotest-assertions-core-jvm", version.ref = "kotest" }
kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
kotlinx-coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1"
nexus-publish = { module = "io.github.gradle-nexus:publish-plugin", version.ref = "nexus-publish" }
testkit = { module = "io.github.mirko-felice.testkit:core", version.ref = "testkit" }

[bundles]
kotlin-testing = [ "kotest-junit5-jvm", "kotest-assertions-core-jvm", "konf-yaml" ]
kotlin-testing = [ "kotest-junit5-jvm", "kotest-assertions-core-jvm" ]

[plugins]
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
Expand Down
76 changes: 0 additions & 76 deletions src/test/kotlin/org/danilopianini/gradle/test/TestingDSL.kt

This file was deleted.

99 changes: 22 additions & 77 deletions src/test/kotlin/org/danilopianini/gradle/test/Tests.kt
Original file line number Diff line number Diff line change
@@ -1,85 +1,30 @@
package org.danilopianini.gradle.test

import com.uchuhimo.konf.Config
import com.uchuhimo.konf.source.yaml
import io.github.classgraph.ClassGraph
import io.github.mirkofelice.api.Testkit
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.file.shouldBeAFile
import io.kotest.matchers.file.shouldExist
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain
import io.kotest.matchers.string.shouldNotContain
import org.gradle.internal.impldep.org.junit.rules.TemporaryFolder
import org.gradle.testkit.runner.BuildResult
import org.gradle.testkit.runner.GradleRunner
import org.gradle.testkit.runner.TaskOutcome
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.File

class Tests : StringSpec(
{
val scan = ClassGraph()
.enableAllInfo()
.acceptPackages(Tests::class.java.`package`.name)
.scan()
scan.getResourcesWithLeafName("test.yaml")
.flatMap { resource ->
log.debug("Found test list in {}", resource)
val yamlFile = File(resource.classpathElementFile.absolutePath + "/" + resource.path)
val testConfiguration = Config { addSpec(Root) }.from.yaml.inputStream(resource.open())
testConfiguration[Root.tests].map { it to yamlFile.parentFile }
}
.forEach { (test, location) ->
log.debug("Test to be executed: {} from {}", test, location)
val testFolder = folder {
location.copyRecursively(this.root)
}
log.debug("Test has been copied into {} and is ready to get executed", testFolder)
test.description {
val result = GradleRunner.create()
.withProjectDir(testFolder.root)
.withPluginClasspath()
.withArguments(test.configuration.tasks + test.configuration.options)
.run { if (test.expectation.failure.isEmpty()) build() else buildAndFail() }
println(result.tasks)
println(result.output)
test.expectation.output_contains.forEach {
result.output shouldContain it
}
test.expectation.output_doesnt_contain.forEach {
result.output shouldNotContain it
}
test.expectation.success.forEach {
result.outcomeOf(it) shouldBe TaskOutcome.SUCCESS
}
test.expectation.failure.forEach {
result.outcomeOf(it) shouldBe TaskOutcome.FAILED
}
test.expectation.not_executed.forEach {
result.task(it) shouldBe null
}
test.expectation.file_exists.forEach {
val file = File("${testFolder.root.absolutePath}/${it.name}").apply {
shouldExist()
shouldBeAFile()
}
it.validate(file)
}
}
}
},
) {
companion object {
val log: Logger = LoggerFactory.getLogger(Tests::class.java)
class Tests : StringSpec({

private fun BuildResult.outcomeOf(name: String) = checkNotNull(task(":$name")?.outcome) {
"Task $name was not present among the executed tasks"
}
val projectName = "publish-on-central"
val sep = File.separator
val baseFolder = Testkit.DEFAULT_TEST_FOLDER + "org${sep}danilopianini${sep}gradle${sep}test$sep"

private fun folder(closure: TemporaryFolder.() -> Unit) = TemporaryFolder().apply {
create()
closure()
}
fun Testkit.projectTest(folder: String) = this.test(projectName, baseFolder + folder)

"Test ktjs" {
Testkit.projectTest("ktjs")
}

"Test ktmultiplatform" {
Testkit.projectTest("ktmultiplatform")
}

"Test multiproject" {
Testkit.projectTest("multiproject")
}

"Test test0" {
Testkit.projectTest("test0")
}
}
})
31 changes: 19 additions & 12 deletions src/test/resources/org/danilopianini/gradle/test/ktjs/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,33 @@ tests:
options:
- '--stacktrace'
expectation:
success: *tasks1
file_exists: &exists
- name: /build/libs/ktjs-1.0.0-sources.jar
outcomes:
success: *tasks1
files:
existing: &exists
- name: /build/libs/ktjs-1.0.0-sources.jar
- description: "Task :jsSourcesJar should generate sources Jar with for Kotlin Js projects"
configuration:
tasks: &tasks2
- 'jsSourcesJar'
options:
- '--stacktrace'
expectation:
success: *tasks2
file_exists: *exists
outcomes:
success: *tasks2
files:
existing: *exists
- description: "Task :kotlinSourcesJar should generate sources Jar with for Kotlin Js projects"
configuration:
tasks: &tasks3
- 'kotlinSourcesJar'
options:
- '--stacktrace'
expectation:
success: *tasks3
file_exists: *exists
outcomes:
success: *tasks3
files:
existing: *exists
- description: "Publishing should only use :jsSourcesJar to create sources Jars"
configuration:
tasks:
Expand All @@ -35,8 +41,9 @@ tests:
- '--dry-run'
- '--stacktrace'
expectation:
output_contains:
- ":kotlinSourcesJar SKIPPED"
output_doesnt_contain:
- ":sourcesJar"
- ":jsSourcesJar"
output:
contains:
- ":kotlinSourcesJar SKIPPED"
doesntContain:
- ":sourcesJar"
- ":jsSourcesJar"
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,32 @@ tests:
options:
- '--stacktrace'
expectation:
success: *tasks
outcomes:
success: *tasks
- description: "gradle should generate nexus lifecycle management tasks in multiplatform projects"
configuration:
tasks:
- tasks
expectation:
success: tasks
output_contains:
- releaseStagingRepositoryOnMavenCentral
- createStagingRepositoryOnMavenCentral
- closeStagingRepositoryOnMavenCentral
- uploadAllPublicationsToMavenCentralNexus
outcomes:
success:
- tasks
output:
contains:
- releaseStagingRepositoryOnMavenCentral
- createStagingRepositoryOnMavenCentral
- closeStagingRepositoryOnMavenCentral
- uploadAllPublicationsToMavenCentralNexus
- description: "dokkaHtml works"
configuration:
tasks:
- dokkaHtml
options:
- '--stacktrace'
expectation:
success: dokkaHtml
outcomes:
success:
- dokkaHtml
- description: "javadocJar should rely on dokkaHtml instead of dokkaJavadoc"
configuration:
tasks:
Expand All @@ -38,9 +44,13 @@ tests:
- '--info'
- '--stacktrace'
expectation:
success: dokkaHtml
not_executed: dokkaJavadoc
output_contains:
- "Dokka plugin found, hence javadocJar will be configured"
- "Lazily configure javadocJar task to depend on Dokka task"
- "Actually configure javadocJar task to depend on Dokka task dokkaHtml"
outcomes:
success:
- dokkaHtml
notExecuted:
- dokkaJavadoc
output:
contains:
- "Dokka plugin found, hence javadocJar will be configured"
- "Lazily configure javadocJar task to depend on Dokka task"
- "Actually configure javadocJar task to depend on Dokka task dokkaHtml"
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ tests:
- '--all'
- '--stacktrace'
expectation:
success: *tasks
output_contains:
- releaseStagingRepositoryOnMavenCentral
- createStagingRepositoryOnMavenCentral
- closeStagingRepositoryOnMavenCentral
- uploadAllPublicationsToMavenCentralNexus
output_doesnt_contain:
- :releaseStagingRepositoryOnMavenCentral
- :createStagingRepositoryOnMavenCentral
- :closeStagingRepositoryOnMavenCentral
outcomes:
success: *tasks
output:
contains:
- releaseStagingRepositoryOnMavenCentral
- createStagingRepositoryOnMavenCentral
- closeStagingRepositoryOnMavenCentral
- uploadAllPublicationsToMavenCentralNexus
doesntContain:
- :releaseStagingRepositoryOnMavenCentral
- :createStagingRepositoryOnMavenCentral
- :closeStagingRepositoryOnMavenCentral
Loading

0 comments on commit d376bec

Please sign in to comment.