From 07ffa681eb34d4aade445a763b8a8dca81a79b69 Mon Sep 17 00:00:00 2001 From: Jan Cizmar Date: Sat, 12 Oct 2024 20:53:13 +0200 Subject: [PATCH] chore: Make tests faster (#2569) --- .../testDataBuilder/TestDataService.kt | 13 +++++++--- .../io/tolgee/BatchJobCleanerListener.kt | 13 ++++++++++ .../main/kotlin/io/tolgee/BatchJobTestUtil.kt | 24 +++++++++++++++++++ .../kotlin/io/tolgee/CleanDbTestListener.kt | 22 ++++++++++++++++- .../testing/AbstractTransactionalTest.kt | 2 ++ 5 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 backend/testing/src/main/kotlin/io/tolgee/BatchJobCleanerListener.kt create mode 100644 backend/testing/src/main/kotlin/io/tolgee/BatchJobTestUtil.kt diff --git a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/TestDataService.kt b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/TestDataService.kt index e28bc46a2f..5c9399cce7 100644 --- a/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/TestDataService.kt +++ b/backend/data/src/main/kotlin/io/tolgee/development/testDataBuilder/TestDataService.kt @@ -433,9 +433,12 @@ class TestDataService( private fun saveAllUsers(builder: TestDataBuilder) { val userAccountBuilders = builder.data.userAccounts userAccountService.saveAll( - userAccountBuilders.map { - it.self.password = passwordEncoder.encode(it.rawPassword) - it.self + userAccountBuilders.map { userBuilder -> + userBuilder.self.password = + passwordHashCache.computeIfAbsent(userBuilder.rawPassword) { + passwordEncoder.encode(userBuilder.rawPassword) + } + userBuilder.self }, ) saveUserAvatars(userAccountBuilders) @@ -500,4 +503,8 @@ class TestDataService( private fun clearEntityManager() { entityManager.clear() } + + companion object { + private val passwordHashCache = mutableMapOf() + } } diff --git a/backend/testing/src/main/kotlin/io/tolgee/BatchJobCleanerListener.kt b/backend/testing/src/main/kotlin/io/tolgee/BatchJobCleanerListener.kt new file mode 100644 index 0000000000..0522957e08 --- /dev/null +++ b/backend/testing/src/main/kotlin/io/tolgee/BatchJobCleanerListener.kt @@ -0,0 +1,13 @@ +package io.tolgee + +import io.tolgee.BatchJobTestUtil.pauseAndClearBatchJobs +import io.tolgee.BatchJobTestUtil.resumeBatchJobs +import org.springframework.test.context.TestContext +import org.springframework.test.context.TestExecutionListener + +class BatchJobCleanerListener : TestExecutionListener { + override fun beforeTestMethod(testContext: TestContext) { + pauseAndClearBatchJobs(testContext) + resumeBatchJobs(testContext) + } +} diff --git a/backend/testing/src/main/kotlin/io/tolgee/BatchJobTestUtil.kt b/backend/testing/src/main/kotlin/io/tolgee/BatchJobTestUtil.kt new file mode 100644 index 0000000000..3d4264c279 --- /dev/null +++ b/backend/testing/src/main/kotlin/io/tolgee/BatchJobTestUtil.kt @@ -0,0 +1,24 @@ +package io.tolgee + +import io.tolgee.batch.BatchJobChunkExecutionQueue +import io.tolgee.batch.BatchJobConcurrentLauncher +import org.springframework.test.context.TestContext + +object BatchJobTestUtil { + fun resumeBatchJobs(testContext: TestContext) { + getBatchJobConcurrentLauncher(testContext).pause = false + } + + fun pauseAndClearBatchJobs(testContext: TestContext) { + getBatchJobConcurrentLauncher(testContext).pause = true + getBatchJobExecutionQueue(testContext).clear() + } + + private fun getBatchJobExecutionQueue(testContext: TestContext): BatchJobChunkExecutionQueue { + return testContext.applicationContext.getBean(BatchJobChunkExecutionQueue::class.java) + } + + private fun getBatchJobConcurrentLauncher(testContext: TestContext): BatchJobConcurrentLauncher { + return testContext.applicationContext.getBean(BatchJobConcurrentLauncher::class.java) + } +} diff --git a/backend/testing/src/main/kotlin/io/tolgee/CleanDbTestListener.kt b/backend/testing/src/main/kotlin/io/tolgee/CleanDbTestListener.kt index a0f4ddad36..0c69d38c09 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/CleanDbTestListener.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/CleanDbTestListener.kt @@ -58,7 +58,6 @@ class CleanDbTestListener : TestExecutionListener { } } } - i++ } } @@ -90,12 +89,21 @@ class CleanDbTestListener : TestExecutionListener { while (rs.next()) { tables.add(rs.getString(1) to rs.getString(2)) } + + val disableConstraintsSQL = generateDisableConstraintsSQL(tables) + disableConstraintsSQL.forEach { stmt.addBatch(it) } + stmt.executeBatch() + stmt.execute( java.lang.String.format( "TRUNCATE TABLE %s", tables.joinToString(",") { it.first + "." + it.second }, ), ) + + val enableConstraintsSQL = generateEnableConstraintsSQL(tables) + enableConstraintsSQL.forEach { stmt.addBatch(it) } + stmt.executeBatch() } catch (e: InterruptedException) { stmt.cancel() throw e @@ -103,6 +111,18 @@ class CleanDbTestListener : TestExecutionListener { } } + private fun generateDisableConstraintsSQL(tables: List>): List { + return tables.map { (schema, table) -> + "ALTER TABLE \"$schema\".\"$table\" DISABLE TRIGGER ALL" + } + } + + private fun generateEnableConstraintsSQL(tables: List>): List { + return tables.map { (schema, table) -> + "ALTER TABLE \"$schema\".\"$table\" ENABLE TRIGGER ALL" + } + } + @Throws(Exception::class) override fun afterTestMethod(testContext: TestContext) { } diff --git a/backend/testing/src/main/kotlin/io/tolgee/testing/AbstractTransactionalTest.kt b/backend/testing/src/main/kotlin/io/tolgee/testing/AbstractTransactionalTest.kt index 4079edb18b..c358039252 100644 --- a/backend/testing/src/main/kotlin/io/tolgee/testing/AbstractTransactionalTest.kt +++ b/backend/testing/src/main/kotlin/io/tolgee/testing/AbstractTransactionalTest.kt @@ -1,5 +1,6 @@ package io.tolgee.testing +import io.tolgee.BatchJobCleanerListener import io.tolgee.CleanDbTestListener import jakarta.persistence.EntityManager import org.springframework.beans.factory.annotation.Autowired @@ -16,6 +17,7 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi DependencyInjectionTestExecutionListener::class, CleanDbTestListener::class, DirtiesContextTestExecutionListener::class, + BatchJobCleanerListener::class, ], ) @ActiveProfiles(profiles = ["local"])