-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Adds Testcontainers support for kotest(kotlintest) #2533
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
Closed
Closed
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
cd4781b
Adds TestContainer support in kotest
ashishkujoy 9571cf6
Upgrades kotest to latest 4.0.3
ashishkujoy b45b02c
Removes usage of ContainerPerSpecListener and ContainerPerSpecListene…
ashishkujoy ccabb4d
Adds example of ContainerPerSpecListener and ContainerPerSpecListener…
ashishkujoy 9f33df6
Moves kotest examples to docs
ashishkujoy 0d312ce
Removes kotest from docs, renames listener, add extension function fo…
ashishkujoy 2e7bb58
Removes mockk dependency
ashishkujoy b75fcc3
Removes delay between test and use alpine image for containers
ashishkujoy 636567a
Makes StartablePerSpecListener and StartablePerTestListener as private
ashishkujoy fbfecb3
Removes private keyword from StartablePerSpecListener and StartablePe…
ashishkujoy 3bfdc06
Replace container based test with mock implementation of startable
ashishkujoy e9b3a61
Fixes failing test
ashishkujoy 14c514c
Makes StartablePerSpecListener and StartablePerTestListener internal …
ashishkujoy 4d93f7d
Adds support for TestLifecycleAware
ashishkujoy f03e1c1
Removes TestLifecycleAwareListener and call TestLifecycleAware method…
ashishkujoy 38b6862
Updates doc
ashishkujoy 5572b99
Adds test around test descriptor name
ashishkujoy 439876a
Encode test name to make it filesystemFriendlyName and updates docs
ashishkujoy 2bd5127
Moves TestLifecycleAwareListener in a separate file
ashishkujoy cf4b30b
Adds TestLifecycleAware support in StartablePerSpecListener
ashishkujoy 64eda9f
Adds a test to verify TestLifecycleAwareListener does not fail when s…
ashishkujoy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| plugins { | ||
| id "org.jetbrains.kotlin.jvm" version "1.3.71" | ||
| id "org.jetbrains.kotlin.kapt" version "1.3.71" | ||
| } | ||
|
|
||
| ext { | ||
| kotestVersion = "4.0.3" | ||
| } | ||
|
|
||
| sourceCompatibility = 1.8 | ||
|
|
||
| repositories { | ||
| mavenCentral() | ||
| } | ||
|
|
||
| dependencies { | ||
| compile project(':testcontainers') | ||
| api("io.kotest:kotest-runner-junit5-jvm:$kotestVersion") | ||
| implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") | ||
| testImplementation("io.kotest:kotest-assertions-core-jvm:$kotestVersion") | ||
| } | ||
|
|
||
|
|
||
| test { | ||
| useJUnitPlatform() | ||
| } | ||
|
|
||
| compileTestKotlin { | ||
| kotlinOptions { | ||
| jvmTarget = "1.8" | ||
| javaParameters = true | ||
| } | ||
| } | ||
| compileKotlin { | ||
| kotlinOptions { | ||
| jvmTarget = "1.8" | ||
| } | ||
| } |
7 changes: 7 additions & 0 deletions
7
modules/kotest/src/main/kotlin/org/testcontainers/containers/Extensions.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package org.testcontainers.containers | ||
|
|
||
| import io.kotest.core.listeners.TestListener | ||
| import org.testcontainers.lifecycle.Startable | ||
|
|
||
| fun Startable.perTest(): TestListener = StartablePerTestListener(this) | ||
| fun Startable.perSpec(): TestListener = StartablePerSpecListener(this) |
52 changes: 52 additions & 0 deletions
52
modules/kotest/src/main/kotlin/org/testcontainers/containers/StartablePerSpecListener.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| package org.testcontainers.containers | ||
|
|
||
| import io.kotest.core.listeners.TestListener | ||
| import io.kotest.core.spec.Spec | ||
| import io.kotest.core.test.TestCase | ||
| import io.kotest.core.test.TestResult | ||
| import kotlinx.coroutines.Dispatchers | ||
| import kotlinx.coroutines.withContext | ||
| import org.testcontainers.lifecycle.Startable | ||
| import org.testcontainers.lifecycle.TestLifecycleAware | ||
|
|
||
|
|
||
| /** | ||
| * [StartablePerSpecListener] starts the given [startable] before execution of any test in the spec | ||
| * and stops after execution of all tests. If the [startable] also inherit from [TestLifecycleAware] | ||
| * then its [beforeTest] and [afterTest] method are also called by the listener. | ||
| * | ||
| * [startable] can any of [GenericContainer] [DockerComposeContainer] [LocalStackContainer] etc. | ||
| * | ||
| * This listener should be used when you want to use a single container for all tests in a single spec class. | ||
| * | ||
| * @see | ||
| * [StartablePerTestListener] | ||
| * */ | ||
|
|
||
| internal class StartablePerSpecListener(private val startable: Startable) : TestListener { | ||
| private val testLifecycleAwareListener = TestLifecycleAwareListener(startable) | ||
|
|
||
| override suspend fun beforeSpec(spec: Spec) { | ||
| withContext(Dispatchers.IO) { | ||
| startable.start() | ||
| } | ||
| } | ||
|
|
||
| override suspend fun beforeTest(testCase: TestCase) { | ||
| withContext(Dispatchers.IO) { | ||
| testLifecycleAwareListener.beforeTest(testCase) | ||
| } | ||
| } | ||
|
|
||
| override suspend fun afterSpec(spec: Spec) { | ||
| withContext(Dispatchers.IO) { | ||
| startable.stop() | ||
| } | ||
| } | ||
|
|
||
| override suspend fun afterTest(testCase: TestCase, result: TestResult) { | ||
| withContext(Dispatchers.IO) { | ||
| testLifecycleAwareListener.afterTest(testCase, result) | ||
| } | ||
| } | ||
| } | ||
40 changes: 40 additions & 0 deletions
40
modules/kotest/src/main/kotlin/org/testcontainers/containers/StartablePerTestListener.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| package org.testcontainers.containers | ||
|
|
||
| import io.kotest.core.listeners.TestListener | ||
| import io.kotest.core.test.TestCase | ||
| import io.kotest.core.test.TestResult | ||
| import kotlinx.coroutines.Dispatchers | ||
| import kotlinx.coroutines.withContext | ||
| import org.testcontainers.lifecycle.Startable | ||
| import org.testcontainers.lifecycle.TestLifecycleAware | ||
|
|
||
|
|
||
| /** | ||
| * [StartablePerTestListener] starts the given [startable] before execution of each test in the spec | ||
| * and stops after execution of each test. If the [startable] also inherit from [TestLifecycleAware] | ||
| * then its [beforeTest] and [afterTest] method are also called by the listener. | ||
| * | ||
| * [startable] can any of [GenericContainer] [DockerComposeContainer] [LocalStackContainer] etc. | ||
| * | ||
| * This should be used when you want a fresh container for each test. | ||
| * | ||
| * @see[StartablePerSpecListener] | ||
| * */ | ||
| internal class StartablePerTestListener(private val startable: Startable) : TestListener { | ||
| private val testLifecycleAwareListener = TestLifecycleAwareListener(startable) | ||
|
|
||
| override suspend fun beforeTest(testCase: TestCase) { | ||
| withContext(Dispatchers.IO) { | ||
| testLifecycleAwareListener.beforeTest(testCase) | ||
| startable.start() | ||
| } | ||
| } | ||
|
|
||
| override suspend fun afterTest(testCase: TestCase, result: TestResult) { | ||
| withContext(Dispatchers.IO) { | ||
| testLifecycleAwareListener.afterTest(testCase, result) | ||
| startable.stop() | ||
| } | ||
| } | ||
| } | ||
|
|
33 changes: 33 additions & 0 deletions
33
modules/kotest/src/main/kotlin/org/testcontainers/containers/TestLifecycleAwareListener.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| package org.testcontainers.containers | ||
|
|
||
| import io.kotest.core.listeners.TestListener | ||
| import io.kotest.core.test.TestCase | ||
| import io.kotest.core.test.TestResult | ||
| import org.testcontainers.lifecycle.Startable | ||
| import org.testcontainers.lifecycle.TestDescription | ||
| import org.testcontainers.lifecycle.TestLifecycleAware | ||
| import java.net.URLEncoder | ||
| import java.util.* | ||
|
|
||
| internal class TestLifecycleAwareListener(startable: Startable) : TestListener { | ||
| private val testLifecycleAware = startable as? TestLifecycleAware | ||
|
|
||
| override suspend fun beforeTest(testCase: TestCase) { | ||
| testLifecycleAware?.beforeTest(testCase.toTestDescription()) | ||
| } | ||
|
|
||
| override suspend fun afterTest(testCase: TestCase, result: TestResult) { | ||
| testLifecycleAware?.afterTest(testCase.toTestDescription(), Optional.ofNullable(result.error)) | ||
| } | ||
| } | ||
|
|
||
| private fun TestCase.toTestDescription() = object : TestDescription { | ||
|
|
||
| override fun getFilesystemFriendlyName(): String { | ||
| return URLEncoder.encode(name, "UTF-8") | ||
| } | ||
|
|
||
| override fun getTestId(): String { | ||
| return description.id() | ||
| } | ||
| } |
16 changes: 16 additions & 0 deletions
16
modules/kotest/src/test/kotlin/org/testcontainers/containers/StartableTestLifecycleAware.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package org.testcontainers.containers | ||
|
|
||
| import org.testcontainers.lifecycle.TestDescription | ||
| import org.testcontainers.lifecycle.TestLifecycleAware | ||
| import java.util.* | ||
|
|
||
| internal class StartableTestLifecycleAware : TestStartable(), TestLifecycleAware { | ||
| val testDescriptions = mutableListOf<TestDescription?>() | ||
|
|
||
| override fun beforeTest(description: TestDescription?) { | ||
| testDescriptions.add(description) | ||
| } | ||
|
|
||
| override fun afterTest(description: TestDescription?, throwable: Optional<Throwable>?) { | ||
| } | ||
| } |
21 changes: 21 additions & 0 deletions
21
...s/kotest/src/test/kotlin/org/testcontainers/containers/StartableTestLifecycleAwareTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| package org.testcontainers.containers | ||
|
|
||
| import io.kotest.core.spec.style.StringSpec | ||
| import io.kotest.matchers.collections.shouldHaveSize | ||
|
|
||
| class StartableTestLifecycleAwareTest : StringSpec({ | ||
| val startableTestLifecycleAwareForPerTest = StartableTestLifecycleAware() | ||
| val startableTestLifecycleAwareForPerSpec = StartableTestLifecycleAware() | ||
|
|
||
| listeners(startableTestLifecycleAwareForPerTest.perTest(), startableTestLifecycleAwareForPerSpec.perSpec()) | ||
|
|
||
| "beforeTestCount for first test should be one" { | ||
| startableTestLifecycleAwareForPerTest.testDescriptions shouldHaveSize 1 | ||
| startableTestLifecycleAwareForPerSpec.testDescriptions shouldHaveSize 1 | ||
| } | ||
|
|
||
| "beforeTestCount for second test should be two" { | ||
| startableTestLifecycleAwareForPerTest.testDescriptions shouldHaveSize 2 | ||
| startableTestLifecycleAwareForPerTest.testDescriptions shouldHaveSize 2 | ||
| } | ||
| }) |
17 changes: 17 additions & 0 deletions
17
...st/src/test/kotlin/org/testcontainers/containers/TestContainerKotestIntegrationPerTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package org.testcontainers.containers | ||
|
|
||
| import io.kotest.core.spec.style.StringSpec | ||
| import io.kotest.matchers.shouldBe | ||
|
|
||
| class TestContainerKotestIntegrationPerTest : StringSpec({ | ||
| val testStartable = TestStartable() | ||
| listeners(testStartable.perTest()) | ||
|
|
||
| "start count for first test should be one" { | ||
| testStartable.startCount shouldBe 1 | ||
| } | ||
|
|
||
| "start count for second test should be two" { | ||
| testStartable.startCount shouldBe 2 | ||
| } | ||
| }) |
30 changes: 30 additions & 0 deletions
30
...es/kotest/src/test/kotlin/org/testcontainers/containers/TestLifecycleAwareListenerTest.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package org.testcontainers.containers | ||
|
|
||
| import io.kotest.core.spec.style.StringSpec | ||
| import io.kotest.matchers.shouldBe | ||
|
|
||
| class TestLifecycleAwareListenerTest : StringSpec({ | ||
| val startableTestLifecycleAware = StartableTestLifecycleAware() | ||
| val startable = TestStartable() | ||
| val testLifecycleAwareListener = TestLifecycleAwareListener(startableTestLifecycleAware) | ||
| val anotherTestLifecycleAwareListener = TestLifecycleAwareListener(startable) | ||
|
|
||
| listeners(testLifecycleAwareListener, anotherTestLifecycleAwareListener) | ||
|
|
||
| "it should not break for listener having startable which is not of type testLifecycleAware" { | ||
| startable.startCount shouldBe 0 | ||
| } | ||
|
|
||
| "test id in test description should be combination of test name and package name" { | ||
| val testDescription = startableTestLifecycleAware.testDescriptions[1] | ||
| testDescription?.testId shouldBe "org.testcontainers.containers.TestLifecycleAwareListenerTest/test id in test" + | ||
| " description should be combination of test name and package name" | ||
| } | ||
|
|
||
| "fileSystemFriendlyName .. in /// test description should be encoded test name" { | ||
| val testDescription = startableTestLifecycleAware.testDescriptions[2] | ||
| val encodedTestName = "fileSystemFriendlyName+..+in+%2F%2F%2F+test+description+should+be+encoded+test+name" | ||
|
|
||
| testDescription?.filesystemFriendlyName shouldBe encodedTestName | ||
| } | ||
| }) |
12 changes: 12 additions & 0 deletions
12
modules/kotest/src/test/kotlin/org/testcontainers/containers/TestStartable.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package org.testcontainers.containers | ||
|
|
||
| import org.testcontainers.lifecycle.Startable | ||
|
|
||
| internal open class TestStartable : Startable { | ||
| var startCount = 0 | ||
| override fun start() { | ||
| startCount++ | ||
| } | ||
| override fun stop() { | ||
| } | ||
| } |
17 changes: 17 additions & 0 deletions
17
...st/src/test/kotlin/org/testcontainers/containers/TestcontainerKotestIntegrationPerSpec.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| package org.testcontainers.containers | ||
|
|
||
| import io.kotest.core.spec.style.StringSpec | ||
| import io.kotest.matchers.shouldBe | ||
|
|
||
| class TestcontainerKotestIntegrationPerSpec : StringSpec({ | ||
| val testStartable = TestStartable() | ||
| listeners(testStartable.perSpec()) | ||
|
|
||
| "start count for first test should be one" { | ||
| testStartable.startCount shouldBe 1 | ||
| } | ||
|
|
||
| "start count for second test should also be one" { | ||
| testStartable.startCount shouldBe 1 | ||
| } | ||
| }) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TestLifecycleAwaresupport is still missing...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TestLifecycleAware has two methods beforeTest and afterTest, as whereas SpecListener are for runnig before and after the entire spec(Test class). Thats the reason i have not added it there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please see other integrations
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ashishkujoy As I understand it, if the startable is a TestLifecycleAware, then we should call beforeTest and afterTest on it, as the container may need to do "other things" between tests, even if we're registering it on the spec (class) level.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The documentation needs to be corrected:
This should be use when you want to a single container for all test in a single test class.
to
This listener should be used when you want to use a single container for all tests in a single spec class.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sksamuel That would be difficult because the before and after test functions in TestLifecylceAware takes TestDescription as parameter which in itself needs testId and testName and these informations are not present in Spec class which we receive in beforeSpec and afterSpec callback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could store them in a variable in the beforeSpec callback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
support added
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ashishkujoy please do not resolve conversations started by others. e.g. this one remains unresolved, in fact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
something to improve in kotest? Other test frameworks don't have this problem.