Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable GC for Kotest #216

Merged
merged 3 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package com.example.kotest
import com.diffplug.selfie.kotest.SelfieExtension

class KotestConfig : io.kotest.core.config.AbstractProjectConfig() {
override fun extensions() = listOf(SelfieExtension)
override fun extensions() = listOf(SelfieExtension(this))
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,23 @@ class SelfieExtension(projectConfig: AbstractProjectConfig) :
kclass: KClass<out Spec>,
results: Map<TestCase, TestResult>,
) {
val file = SnapshotSystemJUnit5.forClass(kclass.java.name)
results.entries.forEach {
if (it.value.isIgnored) {
file.startTest(it.key.name.testName, false)
file.finishedTestWithSuccess(it.key.name.testName, false, false)
}
}
SnapshotSystemJUnit5.forClass(kclass.java.name)
.decrementContainersWithSuccess(results.values.all { it.isSuccess })
}
/**
* If you run from the CLI, `SelfieTestExecutionListener` will run and so will `afterProject`
* below If you run using the Kotest IDE plugin
* - if you run a whole spec, `SelfieTestExecutionListener` will run and so will `afterProject`
* below
* - if you run a single test, `SelfieTestExecutionListener` will not run, but `afterProject`
* below will
*/
override suspend fun afterProject() {
SnapshotSystemJUnit5.finishedAllTests()
// If you run from the CLI, `SelfieTestExecutionListener` will run and so will `afterProject`
// below If you run using the Kotest IDE plugin
// - entire spec -> `SelfieTestExecutionListener` will run and so will `afterProject`
// - single test -> `SelfieTestExecutionListener` will not run, but `afterProject` will
if (!SnapshotSystemJUnit5.testListenerRunning.get()) {
SnapshotSystemJUnit5.finishedAllTests()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class SelfieTestExecutionListener : TestExecutionListener {
private val system = SnapshotSystemJUnit5
override fun executionStarted(testIdentifier: TestIdentifier) {
try {
system.testListenerRunning.set(true)
if (isRootOrKotest(testIdentifier)) return
val (clazz, test) = parseClassTest(testIdentifier)
val snapshotFile = system.forClass(clazz)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ internal object SnapshotSystemJUnit5 : SnapshotSystem {
override fun writeInline(literalValue: LiteralValue<*>, call: CallStack) {
inlineWriteTracker.record(call, literalValue, layout)
}
internal val testListenerRunning = AtomicBoolean(false)
fun finishedAllTests() {
val snapshotsFilesWrittenToDisk =
checkForInvalidStale.getAndUpdate { null }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
package com.diffplug.selfie.kotest

import com.diffplug.selfie.guts.CoroutineDiskStorage
import io.kotest.core.config.AbstractProjectConfig
import io.kotest.core.extensions.Extension
import io.kotest.core.extensions.TestCaseExtension
import io.kotest.core.listeners.AfterProjectListener
import io.kotest.core.listeners.FinalizeSpecListener
import io.kotest.core.listeners.IgnoredSpecListener
import io.kotest.core.source.SourceRef
import io.kotest.core.spec.Spec
import io.kotest.core.test.TestCase
Expand All @@ -29,8 +29,17 @@ import kotlin.reflect.KClass
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.withContext

object SelfieExtension :
Extension, FinalizeSpecListener, TestCaseExtension, IgnoredSpecListener, AfterProjectListener {
class SelfieExtension(projectConfig: AbstractProjectConfig) :
Extension, TestCaseExtension, FinalizeSpecListener, AfterProjectListener {
private fun snapshotFileFor(testCase: TestCase): SnapshotFileProgress {
val classOrFilename: String =
when (val source = testCase.source) {
is SourceRef.ClassSource -> source.fqn
is SourceRef.FileSource -> source.fileName
is SourceRef.None -> TODO("Handle SourceRef.None")
}
return SnapshotSystemKotest.forClassOrFilename(classOrFilename)
}
/** Called for every test method. */
override suspend fun intercept(
testCase: TestCase,
Expand All @@ -46,25 +55,19 @@ object SelfieExtension :
result
}
}
private fun snapshotFileFor(testCase: TestCase): SnapshotFileProgress {
val classOrFilename: String =
when (val source = testCase.source) {
is SourceRef.ClassSource -> source.fqn
is SourceRef.FileSource -> source.fileName
is SourceRef.None -> TODO("Handle SourceRef.None")
}
return SnapshotSystemKotest.forClassOrFilename(classOrFilename)
}
override suspend fun finalizeSpec(
kclass: KClass<out Spec>,
results: Map<TestCase, TestResult>,
) {
results.keys
.map { snapshotFileFor(it) }
.firstOrNull()
?.let { file -> file.finishedClassWithSuccess(results.values.all { it.isSuccess }) }
val file = results.keys.map { snapshotFileFor(it) }.firstOrNull() ?: return
results.entries.forEach {
if (it.value.isIgnored) {
file.startTest(it.key.name.testName)
file.finishedTestWithSuccess(it.key.name.testName, false)
}
}
file.finishedClassWithSuccess(results.entries.all { it.value.isSuccess })
}
override suspend fun ignoredSpec(kclass: KClass<*>, reason: String?): Unit = Unit
override suspend fun afterProject() {
SnapshotSystemKotest.finishedAllTests()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ internal object SnapshotSystemKotest : SnapshotSystem {
For more info https://selfie.dev/jvm/kotest#selfie-and-coroutines
"""
.trimIndent())
fun finishedAllTests() {
internal fun finishedAllTests() {
val snapshotsFilesWrittenToDisk =
checkForInvalidStale.getAndUpdate { null }
?: throw AssertionError("finishedAllTests() was called more than once.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ import com.diffplug.selfie.kotest.SelfieExtension
import io.kotest.core.config.AbstractProjectConfig

object KotestProjectConfig : AbstractProjectConfig() {
override fun extensions() = listOf(SelfieExtension)
override fun extensions() = listOf(SelfieExtension(this))
}