Skip to content

Commit

Permalink
feat: support kotest
Browse files Browse the repository at this point in the history
  • Loading branch information
jGleitz committed Jan 4, 2021
1 parent bec3465 commit 63dba25
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 18 deletions.
27 changes: 18 additions & 9 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ evaluationDependsOnChildren()
val closeAndReleaseRepository by project.tasks

allprojects {
apply {
plugin("org.jetbrains.dokka")
plugin("de.marcphilipp.nexus-publish")
plugin("org.gradle.maven-publish")
plugin("org.gradle.signing")
}

val sourcesJar by tasks.registering(Jar::class) {
group = "build"
description = "Assembles the source code into a jar"
Expand Down Expand Up @@ -116,15 +123,23 @@ allprojects {
archives(dokkaJar)
}

rootProject.publishing.publications.register<MavenPublication>(name) {
signing {
val signingKey: String? by project
val signingKeyPassword: String? by project
useInMemoryPgpKeys(signingKey, signingKeyPassword)
}

publishing.publications.register<MavenPublication>("maven") {
artifactId = if (extra.has("artifactId")) extra["artifactId"] as String else project.name

from(components["java"])
artifact(sourcesJar)
artifact(dokkaJar)

rootProject.signing.sign(this)
signing.sign(this)

pom {
name.set(provider { "$groupId:$artifactId" })
name.set("$groupId:$artifactId")
description.set("Easily manage test files and directories when testing with Spek!")
inceptionYear.set("2020")
url.set("https://github.com/$githubRepository")
Expand Down Expand Up @@ -171,12 +186,6 @@ val mavenCentral = nexusPublishing.repositories.sonatype {
password.set(ossrhPassword)
}

signing {
val signingKey: String? by project
val signingKeyPassword: String? by project
useInMemoryPgpKeys(signingKey, signingKeyPassword)
}

closeAndReleaseRepository.mustRunAfter(mavenCentral.publishTask)

tasks.register("release") {
Expand Down
29 changes: 29 additions & 0 deletions kotest/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
import org.gradle.api.JavaVersion.VERSION_1_8
import org.jetbrains.dokka.gradle.DokkaTask
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
kotlin("jvm")
id("org.jetbrains.dokka")
}

val artifactId by extra("kotest-files")

dependencies {
val kotestVersion = "4.3.2"

implementation(rootProject)
// Kotest is a peer dependency
compileOnly(name = "kotest-framework-api", version = kotestVersion, group = "io.kotest")

testImplementation(name = "kotest-runner-junit5", version = kotestVersion, group = "io.kotest")
testImplementation(name = "atrium-fluent-en_GB", version = "0.15.0", group = "ch.tutteli.atrium")
}

java {
Expand All @@ -23,3 +34,21 @@ tasks.withType<KotlinCompile> {
jvmTarget = "1.8"
}
}

tasks.compileTestKotlin {
kotlinOptions {
freeCompilerArgs += "-Xopt-in=kotlin.io.path.ExperimentalPathApi"
}
}

tasks.withType<DokkaTask> {
dokkaSourceSets.named("main") {
samples.from("src/test/kotlin/samples/ExampleSpek.kt")
}
}

tasks.withType<Test> {
useJUnitPlatform()
reports.junitXml.isEnabled = true
}

40 changes: 40 additions & 0 deletions kotest/src/main/kotlin/KotestTestFilesAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package de.joshuagleitze.testfiles.kotest

import de.joshuagleitze.testfiles.DefaultTestFiles
import io.kotest.core.listeners.TestListener
import io.kotest.core.spec.AutoScan
import io.kotest.core.spec.Spec
import io.kotest.core.test.TestCase
import io.kotest.core.test.TestResult
import io.kotest.core.test.TestStatus.Error
import io.kotest.core.test.TestStatus.Failure
import io.kotest.core.test.TestStatus.Ignored
import io.kotest.core.test.TestStatus.Success
import kotlin.reflect.KClass

@AutoScan
internal object KotestTestFilesAdapter: TestListener {
override val name: String get() = "testfiles"

override suspend fun prepareSpec(kclass: KClass<out Spec>) {
internalTestFiles.enterScope(kclass.qualifiedName ?: "<anonymous spec>")
}

override suspend fun finalizeSpec(kclass: KClass<out Spec>, results: Map<TestCase, TestResult>) {
internalTestFiles.leaveScope(results.values.map { convert(it) }.reduce { left, right -> left.combineWith(right) })
}

override suspend fun beforeAny(testCase: TestCase) {
internalTestFiles.enterScope(testCase.displayName)
}

override suspend fun afterAny(testCase: TestCase, result: TestResult) {
internalTestFiles.leaveScope(convert(result))
}

private fun convert(result: TestResult) = when (result.status) {
Success -> DefaultTestFiles.TestResult.SUCCESS
Error, Failure -> DefaultTestFiles.TestResult.FAILURE
Ignored -> error("contact breach: kotest should not have called us!")
}
}
13 changes: 13 additions & 0 deletions kotest/src/main/kotlin/testFiles.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package de.joshuagleitze.testfiles.kotest

import de.joshuagleitze.testfiles.DefaultTestFiles
import de.joshuagleitze.testfiles.TestFiles

internal val internalTestFiles: DefaultTestFiles = DefaultTestFiles()

/**
* A [TestFiles] instance that will use the structure of the Kotest tests in this project to create files.
*
* @sample de.joshuagleitze.testfiles.kotest.samples.ExampleSpek
*/
public val testFiles: TestFiles get() = internalTestFiles
39 changes: 39 additions & 0 deletions kotest/src/test/kotlin/SpekTestFilesIntegrationSpec.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package de.joshuagleitze.testfiles.kotest

import ch.tutteli.atrium.api.fluent.en_GB.isDirectory
import ch.tutteli.atrium.api.fluent.en_GB.isReadable
import ch.tutteli.atrium.api.fluent.en_GB.isRegularFile
import ch.tutteli.atrium.api.fluent.en_GB.isWritable
import ch.tutteli.atrium.api.fluent.en_GB.parent
import ch.tutteli.atrium.api.fluent.en_GB.toBe
import ch.tutteli.atrium.api.verbs.expect
import ch.tutteli.atrium.core.polyfills.fullName
import de.joshuagleitze.testfiles.DefaultTestFiles
import io.kotest.core.spec.style.DescribeSpec
import kotlin.io.path.div

class KotestTestFilesIntegrationSpec: DescribeSpec({
val fileRoot = DefaultTestFiles.determineTestFilesRootDirectory()

describe("testFiles") {
val expectedGroupFolder = fileRoot / "[${KotestTestFilesIntegrationSpec::class.fullName}]" / "[testFiles]"

it("creates a test file with the appropriate name") {
expect(testFiles.createFile()) {
isRegularFile()
isReadable()
isWritable()
parent.toBe(expectedGroupFolder / "[creates a test file with the appropriate name]")
}
}

it("creates a test directory with the appropriate name") {
expect(testFiles.createDirectory()) {
isDirectory()
isReadable()
isWritable()
parent.toBe(expectedGroupFolder / "[creates a test directory with the appropriate name]")
}
}
}
})
22 changes: 22 additions & 0 deletions kotest/src/test/kotlin/samples/ExampleSpek.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package de.joshuagleitze.testfiles.kotest.samples

import de.joshuagleitze.testfiles.DeletionMode.ALWAYS
import de.joshuagleitze.testfiles.DeletionMode.IF_SUCCESSFUL
import de.joshuagleitze.testfiles.DeletionMode.NEVER
import de.joshuagleitze.testfiles.kotest.testFiles
import io.kotest.core.spec.style.DescribeSpec

class ExampleSpek: DescribeSpec({
describe("using test files") {
it("generates file names") {
testFiles.createFile()
testFiles.createDirectory()
}

it("cleans up files") {
testFiles.createFile("irrelevant", delete = ALWAYS)
testFiles.createFile("default mode", delete = IF_SUCCESSFUL)
testFiles.createFile("output", delete = NEVER)
}
}
})
4 changes: 3 additions & 1 deletion spek/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ plugins {
id("org.jetbrains.dokka")
}

val artifactId by extra("spek-testfiles")

dependencies {
val spekVersion = "2.0.15"

Expand Down Expand Up @@ -48,7 +50,7 @@ tasks.compileTestKotlin {

tasks.withType<DokkaTask> {
dokkaSourceSets.named("main") {
samples.from("src/test/kotlin/ExampleSpek.kt")
samples.from("src/test/kotlin/samples/ExampleSpek.kt")
}
}

Expand Down
2 changes: 1 addition & 1 deletion spek/src/main/kotlin/testFiles.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ import org.spekframework.spek2.dsl.Root
* This function _must_ be called from the root of a Spek before any test is created. That means, for example, that it _must not_ be called
* from the initializer of a `memoized` value. The returned instance should be used throughout the Spek.
*
* @sample de.joshuagleitze.testfiles.spek.ExampleSpek
* @sample de.joshuagleitze.testfiles.spek.samples.ExampleSpek
*/
public fun Root.testFiles(): TestFiles = DefaultTestFiles().also { registerListener(SpekTestFilesAdapter(it)) }
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package de.joshuagleitze.testfiles.spek
package de.joshuagleitze.testfiles.spek.samples

import de.joshuagleitze.testfiles.DeletionMode.ALWAYS
import de.joshuagleitze.testfiles.DeletionMode.IF_SUCCESSFUL
import de.joshuagleitze.testfiles.DeletionMode.NEVER
import de.joshuagleitze.testfiles.spek.testFiles
import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe

Expand Down
12 changes: 6 additions & 6 deletions src/main/kotlin/DefaultTestFiles.kt
Original file line number Diff line number Diff line change
Expand Up @@ -167,26 +167,26 @@ public class DefaultTestFiles: TestFiles {

public enum class TestResult {
SUCCESS {
override fun combineWith(otherResult: TestResult) = when (otherResult) {
public override fun combineWith(otherResult: TestResult): TestResult = when (otherResult) {
SUCCESS -> SUCCESS
FAILURE -> FAILURE
}

override fun shouldBeDeleted(deletionMode: DeletionMode) = when (deletionMode) {
public override fun shouldBeDeleted(deletionMode: DeletionMode): Boolean = when (deletionMode) {
ALWAYS,
IF_SUCCESSFUL -> true
NEVER -> false
}
},
FAILURE {
override fun combineWith(otherResult: TestResult) = FAILURE
override fun shouldBeDeleted(deletionMode: DeletionMode) = when (deletionMode) {
public override fun combineWith(otherResult: TestResult): TestResult = FAILURE
public override fun shouldBeDeleted(deletionMode: DeletionMode): Boolean = when (deletionMode) {
ALWAYS -> true
IF_SUCCESSFUL, NEVER -> false
}
};

internal abstract fun combineWith(otherResult: TestResult): TestResult
internal abstract fun shouldBeDeleted(deletionMode: DeletionMode): Boolean
public abstract fun combineWith(otherResult: TestResult): TestResult
public abstract fun shouldBeDeleted(deletionMode: DeletionMode): Boolean
}
}

0 comments on commit 63dba25

Please sign in to comment.