From dbc2089c8e49c4f7f72287718f883ebe8fd1a863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?O=C4=9Fuzhan=20Soykan?= Date: Tue, 28 May 2024 17:07:02 +0200 Subject: [PATCH] State store (#453) StateStore implementation can be provided outside by the users, thus you can store the state in any other provider such as Gitlab, another file storage or database #370 --- .../com/stove/ktor/example/e2e/ExampleTest.kt | 5 +- .../ktor/example/e2e/TestSystemConfig.kt | 107 +++++++++++------- .../testing/e2e/couchbase/CouchbaseSystem.kt | 9 +- .../e2e/elasticsearch/ElasticsearchSystem.kt | 6 +- .../e2e/standalone/kafka/KafkaSystem.kt | 7 +- .../testing/e2e/mongodb/MongodbSystem.kt | 9 +- .../testing/e2e/rdbms/mssql/MsSqlSystem.kt | 4 +- .../e2e/rdbms/RelationalDatabaseSystem.kt | 4 +- .../stove/testing/e2e/redis/RedisSystem.kt | 4 +- .../testing/e2e/system/TestSystemOptions.kt | 11 +- .../e2e/system/TestSystemOptionsDsl.kt | 16 ++- .../{StateOfSystem.kt => StateStorage.kt} | 94 ++++++++------- .../e2e/system/TestSystemOptionsDslTest.kt | 68 +++++++++++ .../stove/testing/e2e/kafka/KafkaSystem.kt | 7 +- 14 files changed, 231 insertions(+), 120 deletions(-) rename lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/abstractions/{StateOfSystem.kt => StateStorage.kt} (55%) create mode 100644 lib/stove-testing-e2e/src/test/kotlin/com/trendyol/stove/testing/e2e/system/TestSystemOptionsDslTest.kt diff --git a/examples/ktor-example/src/test/kotlin/com/stove/ktor/example/e2e/ExampleTest.kt b/examples/ktor-example/src/test/kotlin/com/stove/ktor/example/e2e/ExampleTest.kt index 2ebb6176..4f3e3206 100644 --- a/examples/ktor-example/src/test/kotlin/com/stove/ktor/example/e2e/ExampleTest.kt +++ b/examples/ktor-example/src/test/kotlin/com/stove/ktor/example/e2e/ExampleTest.kt @@ -11,6 +11,7 @@ import io.kotest.matchers.shouldBe import stove.ktor.example.application.* import stove.ktor.example.domain.* import kotlin.random.Random +import kotlin.time.Duration.Companion.seconds class ExampleTest : FunSpec({ data class ProductOfTest( @@ -56,10 +57,10 @@ class ExampleTest : FunSpec({ } kafka { - shouldBePublished { + shouldBePublished(20.seconds) { actual.id == givenId && actual.name == givenName } - shouldBeConsumed { + shouldBeConsumed(20.seconds) { actual.id == givenId && actual.name == givenName } } diff --git a/examples/ktor-example/src/test/kotlin/com/stove/ktor/example/e2e/TestSystemConfig.kt b/examples/ktor-example/src/test/kotlin/com/stove/ktor/example/e2e/TestSystemConfig.kt index 9c37c109..76a4c658 100644 --- a/examples/ktor-example/src/test/kotlin/com/stove/ktor/example/e2e/TestSystemConfig.kt +++ b/examples/ktor-example/src/test/kotlin/com/stove/ktor/example/e2e/TestSystemConfig.kt @@ -4,61 +4,84 @@ import com.trendol.stove.testing.e2e.rdbms.postgres.* import com.trendyol.stove.testing.e2e.* import com.trendyol.stove.testing.e2e.http.httpClient import com.trendyol.stove.testing.e2e.standalone.kafka.* -import com.trendyol.stove.testing.e2e.system.TestSystem +import com.trendyol.stove.testing.e2e.system.* +import com.trendyol.stove.testing.e2e.system.abstractions.* import com.trendyol.stove.testing.e2e.wiremock.* import io.kotest.core.config.AbstractProjectConfig import org.slf4j.* import stove.ktor.example.app.objectMapperRef +import kotlin.reflect.KClass + +class GitlabStateStorageFactory : StateStorageFactory { + override fun invoke( + options: TestSystemOptions, + system: KClass<*>, + state: KClass + ): StateStorage = object : StateStorage { + override suspend fun capture(start: suspend () -> T): T { + return start() + } + + override fun isSubsequentRun(): Boolean { + return false + } + } +} class TestSystemConfig : AbstractProjectConfig() { private val logger: Logger = LoggerFactory.getLogger("WireMockMonitor") override suspend fun beforeProject() = - TestSystem(baseUrl = "http://localhost:8080") - .with { - httpClient() - bridge() - postgresql { - PostgresqlOptions(configureExposedConfiguration = { cfg -> - listOf( - "database.jdbcUrl=${cfg.jdbcUrl}", - "database.host=${cfg.host}", - "database.port=${cfg.port}", - "database.name=${cfg.database}", - "database.username=${cfg.username}", - "database.password=${cfg.password}" - ) - }) - } - kafka { - stoveKafkaObjectMapperRef = objectMapperRef - KafkaSystemOptions { - listOf( - "kafka.bootstrapServers=${it.bootstrapServers}", - "kafka.interceptorClasses=${it.interceptorClass}" - ) - } - } - wiremock { - WireMockSystemOptions( - port = 9090, - removeStubAfterRequestMatched = true, - afterRequest = { e, _ -> - logger.info(e.request.toString()) - } + TestSystem(baseUrl = "http://localhost:8080") { +// this.stateStorage(GitlabStateStorageFactory()) + if (this.isRunningLocally()) { + enableReuseForTestContainers() + keepDependenciesRunning() + } + }.with { + httpClient() + bridge() + postgresql { + PostgresqlOptions(configureExposedConfiguration = { cfg -> + listOf( + "database.jdbcUrl=${cfg.jdbcUrl}", + "database.host=${cfg.host}", + "database.port=${cfg.port}", + "database.name=${cfg.database}", + "database.username=${cfg.username}", + "database.password=${cfg.password}" + ) + }) + } + kafka { + stoveKafkaObjectMapperRef = objectMapperRef + KafkaSystemOptions { + listOf( + "kafka.bootstrapServers=${it.bootstrapServers}", + "kafka.interceptorClasses=${it.interceptorClass}" ) } - ktor( - withParameters = listOf( - "port=8080" - ), - runner = { parameters -> - stove.ktor.example.run(parameters) { - addTestSystemDependencies() - } + } + wiremock { + WireMockSystemOptions( + port = 9090, + removeStubAfterRequestMatched = true, + afterRequest = { e, _ -> + logger.info(e.request.toString()) } ) - }.run() + } + ktor( + withParameters = listOf( + "port=8080" + ), + runner = { parameters -> + stove.ktor.example.run(parameters) { + addTestSystemDependencies() + } + } + ) + }.run() override suspend fun afterProject() { TestSystem.stop() diff --git a/lib/stove-testing-e2e-couchbase/src/main/kotlin/com/trendyol/stove/testing/e2e/couchbase/CouchbaseSystem.kt b/lib/stove-testing-e2e-couchbase/src/main/kotlin/com/trendyol/stove/testing/e2e/couchbase/CouchbaseSystem.kt index 752556d0..8c60b2fb 100644 --- a/lib/stove-testing-e2e-couchbase/src/main/kotlin/com/trendyol/stove/testing/e2e/couchbase/CouchbaseSystem.kt +++ b/lib/stove-testing-e2e-couchbase/src/main/kotlin/com/trendyol/stove/testing/e2e/couchbase/CouchbaseSystem.kt @@ -27,11 +27,8 @@ class CouchbaseSystem internal constructor( private lateinit var exposedConfiguration: CouchbaseExposedConfiguration private val logger: Logger = LoggerFactory.getLogger(javaClass) - private val state: StateOfSystem = StateOfSystem( - testSystem.options, - CouchbaseSystem::class, - CouchbaseExposedConfiguration::class - ) + private val state: StateStorage = + testSystem.options.createStateStorage() override suspend fun run() { exposedConfiguration = @@ -48,7 +45,7 @@ class CouchbaseSystem internal constructor( cluster = createCluster(exposedConfiguration) collection = cluster.bucket(context.bucket.name).defaultCollection() - if (!state.isSubsequentRun()) { + if (!state.isSubsequentRun() || testSystem.options.runMigrationsAlways) { context.options.migrationCollection.run(cluster) } } diff --git a/lib/stove-testing-e2e-elasticsearch/src/main/kotlin/com/trendyol/stove/testing/e2e/elasticsearch/ElasticsearchSystem.kt b/lib/stove-testing-e2e-elasticsearch/src/main/kotlin/com/trendyol/stove/testing/e2e/elasticsearch/ElasticsearchSystem.kt index 89626f2d..e266e639 100644 --- a/lib/stove-testing-e2e-elasticsearch/src/main/kotlin/com/trendyol/stove/testing/e2e/elasticsearch/ElasticsearchSystem.kt +++ b/lib/stove-testing-e2e-elasticsearch/src/main/kotlin/com/trendyol/stove/testing/e2e/elasticsearch/ElasticsearchSystem.kt @@ -31,8 +31,8 @@ class ElasticsearchSystem internal constructor( private lateinit var exposedConfiguration: ElasticSearchExposedConfiguration private val logger: Logger = LoggerFactory.getLogger(javaClass) - private val state: StateOfSystem = - StateOfSystem(testSystem.options, ElasticsearchSystem::class, ElasticSearchExposedConfiguration::class) + private val state: StateStorage = + testSystem.options.createStateStorage() override suspend fun run() { exposedConfiguration = state.capture { @@ -57,7 +57,7 @@ class ElasticsearchSystem internal constructor( override suspend fun afterRun() { esClient = createEsClient(exposedConfiguration) - if (!state.isSubsequentRun()) { + if (!state.isSubsequentRun() || testSystem.options.runMigrationsAlways) { context.options.migrationCollection.run(esClient) } } diff --git a/lib/stove-testing-e2e-kafka/src/main/kotlin/com/trendyol/stove/testing/e2e/standalone/kafka/KafkaSystem.kt b/lib/stove-testing-e2e-kafka/src/main/kotlin/com/trendyol/stove/testing/e2e/standalone/kafka/KafkaSystem.kt index 6de215c6..c8aa47dd 100644 --- a/lib/stove-testing-e2e-kafka/src/main/kotlin/com/trendyol/stove/testing/e2e/standalone/kafka/KafkaSystem.kt +++ b/lib/stove-testing-e2e-kafka/src/main/kotlin/com/trendyol/stove/testing/e2e/standalone/kafka/KafkaSystem.kt @@ -39,11 +39,8 @@ class KafkaSystem( @PublishedApi internal lateinit var sink: TestSystemMessageSink private val logger: Logger = LoggerFactory.getLogger(javaClass) - private val state: StateOfSystem = StateOfSystem( - testSystem.options, - KafkaSystem::class, - KafkaExposedConfiguration::class - ) + private val state: StateStorage = + testSystem.options.createStateStorage() override suspend fun run() { exposedConfiguration = state.capture { diff --git a/lib/stove-testing-e2e-mongodb/src/main/kotlin/com/trendyol/stove/testing/e2e/mongodb/MongodbSystem.kt b/lib/stove-testing-e2e-mongodb/src/main/kotlin/com/trendyol/stove/testing/e2e/mongodb/MongodbSystem.kt index 9b4a45d6..26aa0e08 100644 --- a/lib/stove-testing-e2e-mongodb/src/main/kotlin/com/trendyol/stove/testing/e2e/mongodb/MongodbSystem.kt +++ b/lib/stove-testing-e2e-mongodb/src/main/kotlin/com/trendyol/stove/testing/e2e/mongodb/MongodbSystem.kt @@ -15,11 +15,6 @@ import org.bson.json.JsonWriterSettings import org.bson.types.ObjectId import org.slf4j.* import reactor.kotlin.core.publisher.toFlux -import kotlin.collections.List -import kotlin.collections.MutableMap -import kotlin.collections.isNullOrEmpty -import kotlin.collections.listOf -import kotlin.collections.plus import kotlin.collections.set @MongoDsl @@ -37,8 +32,8 @@ class MongodbSystem internal constructor( JsonWriterSettings.builder() .objectIdConverter { value, writer -> writer.writeString(value.toHexString()) } .build() - private val state: StateOfSystem = - StateOfSystem(testSystem.options, MongodbSystem::class, MongodbExposedConfiguration::class) + private val state: StateStorage = + testSystem.options.createStateStorage() override suspend fun run() { exposedConfiguration = diff --git a/lib/stove-testing-e2e-rdbms-mssql/src/main/kotlin/com/trendyol/stove/testing/e2e/rdbms/mssql/MsSqlSystem.kt b/lib/stove-testing-e2e-rdbms-mssql/src/main/kotlin/com/trendyol/stove/testing/e2e/rdbms/mssql/MsSqlSystem.kt index ac691a96..e0af8a9c 100644 --- a/lib/stove-testing-e2e-rdbms-mssql/src/main/kotlin/com/trendyol/stove/testing/e2e/rdbms/mssql/MsSqlSystem.kt +++ b/lib/stove-testing-e2e-rdbms-mssql/src/main/kotlin/com/trendyol/stove/testing/e2e/rdbms/mssql/MsSqlSystem.kt @@ -17,8 +17,8 @@ class MsSqlSystem internal constructor( private lateinit var sqlOperations: SqlOperations private lateinit var exposedConfiguration: RelationalDatabaseExposedConfiguration private val logger: Logger = LoggerFactory.getLogger(javaClass) - private val state: StateOfSystem = - StateOfSystem(testSystem.options, javaClass.kotlin, RelationalDatabaseExposedConfiguration::class) + private val state: StateStorage = + testSystem.options.createStateStorage() override suspend fun run() { exposedConfiguration = diff --git a/lib/stove-testing-e2e-rdbms/src/main/kotlin/com/trendyol/stove/testing/e2e/rdbms/RelationalDatabaseSystem.kt b/lib/stove-testing-e2e-rdbms/src/main/kotlin/com/trendyol/stove/testing/e2e/rdbms/RelationalDatabaseSystem.kt index b73be46d..475db91a 100644 --- a/lib/stove-testing-e2e-rdbms/src/main/kotlin/com/trendyol/stove/testing/e2e/rdbms/RelationalDatabaseSystem.kt +++ b/lib/stove-testing-e2e-rdbms/src/main/kotlin/com/trendyol/stove/testing/e2e/rdbms/RelationalDatabaseSystem.kt @@ -21,8 +21,8 @@ abstract class RelationalDatabaseSystem> p protected lateinit var exposedConfiguration: RelationalDatabaseExposedConfiguration protected lateinit var sqlOperations: SqlOperations - protected val state: StateOfSystem, RelationalDatabaseExposedConfiguration> = - StateOfSystem(testSystem.options, javaClass.kotlin, RelationalDatabaseExposedConfiguration::class) + private val state: StateStorage = + testSystem.options.createStateStorage>() protected abstract fun connectionFactory(exposedConfiguration: RelationalDatabaseExposedConfiguration): ConnectionFactory diff --git a/lib/stove-testing-e2e-redis/src/main/kotlin/com/trendyol/stove/testing/e2e/redis/RedisSystem.kt b/lib/stove-testing-e2e-redis/src/main/kotlin/com/trendyol/stove/testing/e2e/redis/RedisSystem.kt index a25300de..bf978e5e 100644 --- a/lib/stove-testing-e2e-redis/src/main/kotlin/com/trendyol/stove/testing/e2e/redis/RedisSystem.kt +++ b/lib/stove-testing-e2e-redis/src/main/kotlin/com/trendyol/stove/testing/e2e/redis/RedisSystem.kt @@ -17,8 +17,8 @@ class RedisSystem( private lateinit var client: RedisClient private lateinit var exposedConfiguration: RedisExposedConfiguration private val logger: Logger = LoggerFactory.getLogger(javaClass) - private val state: StateOfSystem = - StateOfSystem(testSystem.options, RedisSystem::class, RedisExposedConfiguration::class) + private val state: StateStorage = + testSystem.options.createStateStorage() override suspend fun run() { exposedConfiguration = diff --git a/lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/TestSystemOptions.kt b/lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/TestSystemOptions.kt index ea410670..2101ff8f 100644 --- a/lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/TestSystemOptions.kt +++ b/lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/TestSystemOptions.kt @@ -1,3 +1,12 @@ package com.trendyol.stove.testing.e2e.system -data class TestSystemOptions(val keepDependenciesRunning: Boolean = false) +import com.trendyol.stove.testing.e2e.system.abstractions.* + +data class TestSystemOptions( + val keepDependenciesRunning: Boolean = false, + val stateStorageFactory: StateStorageFactory = DefaultStateStorageFactory(), + val runMigrationsAlways: Boolean = false +) { + inline fun createStateStorage(): StateStorage = + (this.stateStorageFactory(this, TSystem::class, TState::class)) +} diff --git a/lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/TestSystemOptionsDsl.kt b/lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/TestSystemOptionsDsl.kt index 87427a40..3550a945 100644 --- a/lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/TestSystemOptionsDsl.kt +++ b/lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/TestSystemOptionsDsl.kt @@ -1,8 +1,8 @@ package com.trendyol.stove.testing.e2e.system +import com.trendyol.stove.testing.e2e.system.abstractions.StateStorageFactory import com.trendyol.stove.testing.e2e.system.annotations.StoveDsl -import org.slf4j.Logger -import org.slf4j.LoggerFactory +import org.slf4j.* @StoveDsl class TestSystemOptionsDsl { @@ -31,6 +31,18 @@ class TestSystemOptionsDsl { @StoveDsl fun enableReuseForTestContainers(): Unit = propertiesFile.enable() + @StoveDsl + fun stateStorage(factory: StateStorageFactory): TestSystemOptionsDsl { + options = options.copy(stateStorageFactory = factory) + return this + } + + @StoveDsl + fun runMigrationsAlways(): TestSystemOptionsDsl { + options = options.copy(runMigrationsAlways = true) + return this + } + private fun isRunningOnCI(): Boolean = System.getenv("CI") == "true" || System.getenv("GITLAB_CI") == "true" || diff --git a/lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/abstractions/StateOfSystem.kt b/lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/abstractions/StateStorage.kt similarity index 55% rename from lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/abstractions/StateOfSystem.kt rename to lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/abstractions/StateStorage.kt index c42b8f0a..b15c2dac 100644 --- a/lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/abstractions/StateOfSystem.kt +++ b/lib/stove-testing-e2e/src/main/kotlin/com/trendyol/stove/testing/e2e/system/abstractions/StateStorage.kt @@ -1,17 +1,37 @@ +@file:Suppress("FunctionName") + package com.trendyol.stove.testing.e2e.system.abstractions import com.fasterxml.jackson.module.kotlin.readValue import com.trendyol.stove.testing.e2e.serialization.StoveObjectMapper -import com.trendyol.stove.testing.e2e.system.TestSystem -import com.trendyol.stove.testing.e2e.system.TestSystemOptions -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import java.nio.file.Path -import java.nio.file.Paths +import com.trendyol.stove.testing.e2e.system.* +import org.slf4j.* +import java.nio.file.* import java.util.* import kotlin.io.path.* import kotlin.reflect.KClass +interface StateStorage { + suspend fun capture(start: suspend () -> TState): TState + + fun isSubsequentRun(): Boolean +} + +interface StateStorageFactory { + operator fun invoke(options: TestSystemOptions, system: KClass<*>, state: KClass): StateStorage +} + +fun DefaultStateStorageFactory(): StateStorageFactory = object : StateStorageFactory { + override fun invoke(options: TestSystemOptions, system: KClass<*>, state: KClass): StateStorage = + DefaultStateStorage(options, system, state) +} + +fun DefaultStateStorage( + options: TestSystemOptions, + system: KClass<*>, + state: KClass +): StateStorage = FileSystemStorage(options, system, state) + /** * Represents the state of the [TestSystem] which is being captured. * @param TState the type of the state @@ -23,28 +43,18 @@ data class StateWithProcess( val processId: Long ) -/** - * Represents the state of the [TestSystem] which is being captured. - * @param TSystem the type of the [TestSystem] - * @param TState the type of the state - * @param options the options of the [TestSystem] - * @param system the [TestSystem] which is being captured - * @param state the state of the [TestSystem] - */ -class StateOfSystem( +internal class FileSystemStorage( val options: TestSystemOptions, - val system: KClass, + val system: KClass<*>, private val state: KClass -) { +) : StateStorage { private val folderForSystem = Paths.get( System.getProperty("java.io.tmpdir"), "com.trendyol.stove.testing.e2e" ) - private val pathForSystem: Path = - folderForSystem.resolve( - "stove-e2e-${system.simpleName!!.lowercase(Locale.getDefault())}.lock" - ) + + private val pathForSystem: Path = folderForSystem.resolve("stove-e2e-${system.simpleName!!.lowercase(Locale.getDefault())}.lock") private val j = StoveObjectMapper.Default private val l: Logger = LoggerFactory.getLogger(javaClass) @@ -58,33 +68,29 @@ class StateOfSystem( * Captures the TestSystem state into the file system. Basically creates a Json file which contains the state of the [PluggedSystem] * that is run by the [TestSystem]. */ - suspend fun capture(start: suspend () -> TState): TState = - when { - !options.keepDependenciesRunning -> { - l.info("State for ${name()} is being deleted at the path: ${pathForSystem.absolutePathString()}") - pathForSystem.deleteIfExists() - start() - } + override suspend fun capture(start: suspend () -> TState): TState = when { + !options.keepDependenciesRunning -> { + l.info("State for ${name()} is being deleted at the path: ${pathForSystem.absolutePathString()}") + pathForSystem.deleteIfExists() + start() + } - pathForSystem.exists() && options.keepDependenciesRunning -> recover(otherwise = start) - !pathForSystem.exists() && options.keepDependenciesRunning -> saveStateForNextRun(start()) - else -> { - pathForSystem.deleteIfExists() - start() - } + pathForSystem.exists() && options.keepDependenciesRunning -> recover(otherwise = start) + !pathForSystem.exists() && options.keepDependenciesRunning -> saveStateForNextRun(start()) + else -> { + pathForSystem.deleteIfExists() + start() } + } /** * Returns true if the [TestSystem] is being run for the first time. */ - fun isSubsequentRun(): Boolean = pathForSystem.exists() && options.keepDependenciesRunning && isDifferentProcess() - - private fun saveStateForNextRun(state: TState): TState = - state.also { - l.info("State does not exist for ${name()}. System is being saved to: ${pathForSystem.absolutePathString()}") - pathForSystem.writeBytes(j.writeValueAsBytes(StateWithProcess(state, getPid()))) - } + override fun isSubsequentRun(): Boolean = pathForSystem.exists() && options.keepDependenciesRunning && isDifferentProcess() + /** + * Recovers the state of the [TestSystem] from the file system. + */ private suspend fun recover(otherwise: suspend () -> TState): TState = when { pathForSystem.exists() -> { @@ -96,6 +102,12 @@ class StateOfSystem( else -> saveStateForNextRun(otherwise()) } + private fun saveStateForNextRun(state: TState): TState = + state.also { + l.info("State does not exist for ${name()}. System is being saved to: ${pathForSystem.absolutePathString()}") + pathForSystem.writeBytes(j.writeValueAsBytes(StateWithProcess(state, getPid()))) + } + private fun isDifferentProcess(): Boolean { val swp: StateWithProcess = j.readValue(pathForSystem.readBytes()) return swp.processId != getPid() diff --git a/lib/stove-testing-e2e/src/test/kotlin/com/trendyol/stove/testing/e2e/system/TestSystemOptionsDslTest.kt b/lib/stove-testing-e2e/src/test/kotlin/com/trendyol/stove/testing/e2e/system/TestSystemOptionsDslTest.kt new file mode 100644 index 00000000..a3e8c505 --- /dev/null +++ b/lib/stove-testing-e2e/src/test/kotlin/com/trendyol/stove/testing/e2e/system/TestSystemOptionsDslTest.kt @@ -0,0 +1,68 @@ +package com.trendyol.stove.testing.e2e.system + +import com.trendyol.stove.testing.e2e.system.abstractions.* +import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.shouldBe +import kotlin.reflect.KClass + +class TestSystemOptionsDslTest : FunSpec({ + test("should keep dependencies running") { + val testSystemOptionsDsl = TestSystemOptionsDsl() + testSystemOptionsDsl.keepDependenciesRunning() + + testSystemOptionsDsl.options.keepDependenciesRunning shouldBe true + } + + test("should check if running locally") { + val testSystemOptionsDsl = TestSystemOptionsDsl() + testSystemOptionsDsl.isRunningLocally() shouldBe ( + System.getenv("CI") != "true" && + System.getenv("GITLAB_CI") != "true" && + System.getenv("GITHUB_ACTIONS") != "true" + ) + } + + test("should enable reuse for test containers") { + val testSystemOptionsDsl = TestSystemOptionsDsl() + testSystemOptionsDsl.enableReuseForTestContainers() + } + + test("should set state storage factory") { + val testSystemOptionsDsl = TestSystemOptionsDsl() + + class AnotherStateStorageFactory : StateStorageFactory { + override fun invoke(options: TestSystemOptions, system: KClass<*>, state: KClass): StateStorage { + return object : StateStorage { + override suspend fun capture(start: suspend () -> T): T { + return start() + } + + override fun isSubsequentRun(): Boolean { + return false + } + } + } + } + + data class Example1ExposedState(val id: Int = 1) : ExposedConfiguration + + class Example1System(override val testSystem: TestSystem) : PluggedSystem { + override fun close() = Unit + } + + val anotherStateStorageFactory = AnotherStateStorageFactory() + testSystemOptionsDsl.stateStorage(anotherStateStorageFactory) + + testSystemOptionsDsl.options.stateStorageFactory shouldBe anotherStateStorageFactory + val storage = testSystemOptionsDsl.options.createStateStorage() + storage.isSubsequentRun() shouldBe false + storage.capture { Example1ExposedState() } shouldBe Example1ExposedState() + } + + test("should run migrations always") { + val testSystemOptionsDsl = TestSystemOptionsDsl() + testSystemOptionsDsl.runMigrationsAlways() + + testSystemOptionsDsl.options.runMigrationsAlways shouldBe true + } +}) diff --git a/starters/spring/stove-spring-testing-e2e-kafka/src/main/kotlin/com/trendyol/stove/testing/e2e/kafka/KafkaSystem.kt b/starters/spring/stove-spring-testing-e2e-kafka/src/main/kotlin/com/trendyol/stove/testing/e2e/kafka/KafkaSystem.kt index bffa288d..83e1320f 100644 --- a/starters/spring/stove-spring-testing-e2e-kafka/src/main/kotlin/com/trendyol/stove/testing/e2e/kafka/KafkaSystem.kt +++ b/starters/spring/stove-spring-testing-e2e-kafka/src/main/kotlin/com/trendyol/stove/testing/e2e/kafka/KafkaSystem.kt @@ -27,11 +27,8 @@ class KafkaSystem( private lateinit var kafkaTemplate: KafkaTemplate private lateinit var exposedConfiguration: KafkaExposedConfiguration val getInterceptor: () -> TestSystemKafkaInterceptor = { applicationContext.getBean() } - private val state: StateOfSystem = StateOfSystem( - testSystem.options, - javaClass.kotlin, - KafkaExposedConfiguration::class - ) + private val state: StateStorage = + testSystem.options.createStateStorage() override suspend fun beforeRun() = Unit