Repo created
This commit is contained in:
parent
75dc487a7a
commit
39c29d175b
6317 changed files with 388324 additions and 2 deletions
19
core/testing/build.gradle.kts
Normal file
19
core/testing/build.gradle.kts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
plugins {
|
||||
id(ThunderbirdPlugins.Library.kmp)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "net.thunderbird.core.testing"
|
||||
}
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
implementation(libs.kotlin.test)
|
||||
implementation(libs.kotlin.test.junit)
|
||||
implementation(libs.kotlinx.coroutines.test)
|
||||
implementation(libs.assertk)
|
||||
implementation(libs.turbine)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
package assertk.assertions
|
||||
|
||||
import assertk.Assert
|
||||
import assertk.assertions.support.expected
|
||||
import assertk.assertions.support.show
|
||||
|
||||
fun <T> Assert<List<T>>.containsNoDuplicates() = given { actual ->
|
||||
val seen: MutableSet<T> = mutableSetOf()
|
||||
val duplicates = actual.filter { !seen.add(it) }
|
||||
if (duplicates.isNotEmpty()) {
|
||||
expected("to contain no duplicates but found: ${show(duplicates)}")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package net.thunderbird.core.testing
|
||||
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.Instant
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
class TestClock(
|
||||
private var currentTime: Instant = Clock.System.now(),
|
||||
) : Clock {
|
||||
override fun now(): Instant = currentTime
|
||||
|
||||
fun changeTimeTo(time: Instant) {
|
||||
currentTime = time
|
||||
}
|
||||
|
||||
fun advanceTimeBy(duration: Duration) {
|
||||
currentTime += duration
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package net.thunderbird.core.testing.coroutines
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.test.TestDispatcher
|
||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||
import kotlinx.coroutines.test.resetMain
|
||||
import kotlinx.coroutines.test.setMain
|
||||
import org.junit.rules.TestWatcher
|
||||
import org.junit.runner.Description
|
||||
|
||||
/**
|
||||
* A JUnit rule that swaps the [kotlinx.coroutines.Dispatchers.Main] dispatcher with a [kotlinx.coroutines.test.TestDispatcher] for the duration of the test.
|
||||
*
|
||||
* Use this rule to ensure that coroutines running on the main dispatcher are executed in a controlled manner during tests.
|
||||
*
|
||||
* This uses [kotlinx.coroutines.test.UnconfinedTestDispatcher] by default, but you can provide a different [kotlinx.coroutines.test.TestDispatcher] if needed.
|
||||
* Especially when testing view models use the [kotlinx.coroutines.test.StandardTestDispatcher], this allows you to
|
||||
* control the execution of coroutines in a more predictable way.
|
||||
*
|
||||
* @param testDispatcher The [kotlinx.coroutines.test.TestDispatcher] to use as the main dispatcher during tests. Defaults to [kotlinx.coroutines.test.UnconfinedTestDispatcher].
|
||||
*/
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class MainDispatcherRule(
|
||||
val testDispatcher: TestDispatcher = UnconfinedTestDispatcher(),
|
||||
) : TestWatcher() {
|
||||
override fun starting(description: Description) {
|
||||
Dispatchers.setMain(testDispatcher)
|
||||
}
|
||||
|
||||
override fun finished(description: Description) {
|
||||
Dispatchers.resetMain()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package assertk.assertions
|
||||
|
||||
import assertk.assertFailure
|
||||
import assertk.assertThat
|
||||
import kotlin.test.Test
|
||||
|
||||
class ListExtensionsKtTest {
|
||||
|
||||
@Test
|
||||
fun `containsNoDuplicates() should succeed with no duplicates`() {
|
||||
val list = listOf("a", "b", "c")
|
||||
|
||||
assertThat(list).containsNoDuplicates()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `containsNoDuplicates() should fail with duplicates`() {
|
||||
val list = listOf("a", "b", "c", "a", "a")
|
||||
|
||||
assertFailure {
|
||||
assertThat(list).containsNoDuplicates()
|
||||
}.hasMessage("""expected to contain no duplicates but found: <["a", "a"]>""")
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package net.thunderbird.core.testing
|
||||
|
||||
import assertk.assertThat
|
||||
import assertk.assertions.isEqualTo
|
||||
import kotlin.test.Test
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.Instant
|
||||
|
||||
@OptIn(ExperimentalTime::class)
|
||||
internal class TestClockTest {
|
||||
|
||||
@Test
|
||||
fun `should return the current time`() {
|
||||
val testClock = TestClock(Instant.DISTANT_PAST)
|
||||
|
||||
val currentTime = testClock.now()
|
||||
|
||||
assertThat(currentTime).isEqualTo(Instant.DISTANT_PAST)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should return the changed time`() {
|
||||
val testClock = TestClock(Instant.DISTANT_PAST)
|
||||
testClock.changeTimeTo(Instant.DISTANT_FUTURE)
|
||||
|
||||
val currentTime = testClock.now()
|
||||
|
||||
assertThat(currentTime).isEqualTo(Instant.DISTANT_FUTURE)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `should advance time by duration`() {
|
||||
val testClock = TestClock(Instant.DISTANT_PAST)
|
||||
testClock.advanceTimeBy(1L.milliseconds)
|
||||
|
||||
val currentTime = testClock.now()
|
||||
|
||||
assertThat(currentTime).isEqualTo(Instant.DISTANT_PAST + 1L.milliseconds)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue