Skip to content

Commit 555c65f

Browse files
committed
Separate test facilities into a separate module and clean up
Move the test facilities lying around `kotlinx-coroutines-core` and their reimplementation in `kotlinx-coroutines-test` into a separate module, on which the other modules now depend. This allows us to have internal testing facilities in common code. After the migration, the test facilities were also refactored a bit: * Removed many SUPPRESS directives, * Extracted a lot of code to multiplatform, * Fixed a couple of bugs in TestBase, * etc. Finally, the tests were cleaned up automatically a bit, most notably by replacing `assertTrue(a is T)` with `assertIs`.
1 parent 08491dc commit 555c65f

File tree

492 files changed

+1493
-1141
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

492 files changed

+1493
-1141
lines changed

build.gradle.kts

+12-20
Original file line numberDiff line numberDiff line change
@@ -108,33 +108,25 @@ configure(subprojects.filter { !sourceless.contains(it.name) }) {
108108
}
109109
}
110110

111+
configure(subprojects.filter { !sourceless.contains(it.name) && it.name != testUtilsModule }) {
112+
if (isMultiplatform) {
113+
configure<KotlinMultiplatformExtension> {
114+
sourceSets.commonTest.dependencies { implementation(project(":$testUtilsModule")) }
115+
}
116+
} else {
117+
dependencies { add("testImplementation", project(":$testUtilsModule")) }
118+
}
119+
}
120+
111121
// Add dependency to the core module in all the other subprojects.
112122
configure(subprojects.filter { !sourceless.contains(it.name) && it.name != coreModule }) {
113123
evaluationDependsOn(":$coreModule")
114-
val jvmTestDependency = project(":$coreModule")
115-
.extensions.getByType(KotlinMultiplatformExtension::class)
116-
.targets["jvm"].compilations["test"].output.allOutputs
117124
if (isMultiplatform) {
118125
configure<KotlinMultiplatformExtension> {
119-
sourceSets {
120-
commonMain {
121-
dependencies {
122-
api(project(":$coreModule"))
123-
}
124-
}
125-
jvmTest {
126-
dependencies {
127-
implementation(jvmTestDependency)
128-
}
129-
}
130-
}
126+
sourceSets.commonMain.dependencies { api(project(":$coreModule")) }
131127
}
132128
} else {
133-
dependencies {
134-
add("api", project(":$coreModule"))
135-
// the only way IDEA can resolve test classes
136-
add("testImplementation", jvmTestDependency)
137-
}
129+
dependencies { add("api", project(":$coreModule")) }
138130
}
139131
}
140132

buildSrc/src/main/kotlin/Projects.kt

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ val Project.sourceSets: SourceSetContainer
2424

2525
val coreModule = "kotlinx-coroutines-core"
2626
val jdk8ObsoleteModule = "kotlinx-coroutines-jdk8"
27-
val testModule = "kotlinx-coroutines-test"
27+
val testUtilsModule = "test-utils"
2828

2929
// Not applicable for Kotlin plugin
3030
val sourceless = setOf("kotlinx.coroutines", "kotlinx-coroutines-bom")
3131

3232
// Not published
33-
val unpublished = setOf("kotlinx.coroutines", "benchmarks", "android-unit-tests")
33+
val unpublished = setOf("kotlinx.coroutines", "benchmarks", "android-unit-tests", testUtilsModule)
3434

35-
val Project.isMultiplatform: Boolean get() = name in setOf(coreModule, testModule)
35+
val Project.isMultiplatform: Boolean get() = name in setOf(coreModule, "kotlinx-coroutines-test", testUtilsModule)
3636
val Project.isBom: Boolean get() = name == "kotlinx-coroutines-bom"
3737

3838
// Projects that we do not check for Android API level 14 check due to various limitations

buildSrc/src/main/kotlin/configure-compilation-conventions.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ configure(subprojects) {
1919
apiVersion = it
2020
versionsAreNotOverridden = false
2121
}
22-
if (isMainTaskName && versionsAreNotOverridden) {
22+
if (isMainTaskName && versionsAreNotOverridden && !unpublished.contains(project.name)) {
2323
allWarningsAsErrors = true
2424
freeCompilerArgs.add("-Xexplicit-api=strict")
2525
}

integration/kotlinx-coroutines-guava/test/FutureAsDeferredUnhandledCompletionExceptionTest.kt

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package kotlinx.coroutines.guava
22

3+
import kotlinx.coroutines.testing.*
34
import com.google.common.util.concurrent.*
45
import kotlinx.coroutines.*
56
import org.junit.*

integration/kotlinx-coroutines-guava/test/ListenableFutureExceptionsTest.kt

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package kotlinx.coroutines.guava
22

3+
import kotlinx.coroutines.testing.*
34
import com.google.common.base.*
45
import com.google.common.util.concurrent.*
56
import kotlinx.coroutines.*

integration/kotlinx-coroutines-guava/test/ListenableFutureTest.kt

+15-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package kotlinx.coroutines.guava
22

3+
import kotlinx.coroutines.testing.*
34
import com.google.common.util.concurrent.*
45
import kotlinx.coroutines.*
56
import org.junit.*
@@ -83,7 +84,7 @@ class ListenableFutureTest : TestBase() {
8384
try {
8485
toAwait.await()
8586
} catch (e: RuntimeException) {
86-
assertTrue(e is IllegalArgumentException)
87+
assertIs<IllegalArgumentException>(e)
8788
e.message!!
8889
} + "K"
8990
}
@@ -97,7 +98,7 @@ class ListenableFutureTest : TestBase() {
9798
try {
9899
toAwait.await()
99100
} catch (e: RuntimeException) {
100-
assertTrue(e is IllegalArgumentException)
101+
assertIs<IllegalArgumentException>(e)
101102
e.message!!
102103
} + "K"
103104
}
@@ -119,7 +120,7 @@ class ListenableFutureTest : TestBase() {
119120
future.get()
120121
fail("'get' should've throw an exception")
121122
} catch (e: ExecutionException) {
122-
assertTrue(e.cause is IllegalStateException)
123+
assertIs<IllegalStateException>(e.cause)
123124
assertEquals("OK", e.cause!!.message)
124125
}
125126
}
@@ -172,7 +173,7 @@ class ListenableFutureTest : TestBase() {
172173
future.get()
173174
} catch (e: ExecutionException) {
174175
assertTrue(future.isDone)
175-
assertTrue(e.cause is OutOfMemoryError)
176+
assertIs<OutOfMemoryError>(e.cause)
176177
}
177178
}
178179

@@ -352,11 +353,11 @@ class ListenableFutureTest : TestBase() {
352353
val asFuture = deferred.asListenableFuture()
353354

354355
val outputCancellationException =
355-
assertFailsWith<CancellationException> { asFuture.get() }
356+
assertFailsWith<CancellationException> { asFuture.get() }
356357
val cause = outputCancellationException.cause
357358
assertNotNull(cause)
358359
assertEquals(cause.message, "Foobar")
359-
assertTrue(cause.cause is OutOfMemoryError)
360+
assertIs<OutOfMemoryError>(cause.cause)
360361
assertEquals(cause.cause?.message, "Foobaz")
361362
}
362363

@@ -392,7 +393,7 @@ class ListenableFutureTest : TestBase() {
392393
assertTrue(asFutureAsDeferred.isCompleted)
393394
// By documentation, join() shouldn't throw when asDeferred is already complete.
394395
asFutureAsDeferred.join()
395-
assertTrue(asFutureAsDeferred.getCompletionExceptionOrNull() is CancellationException)
396+
assertIs<CancellationException>(asFutureAsDeferred.getCompletionExceptionOrNull())
396397
}
397398

398399
@Test
@@ -415,7 +416,7 @@ class ListenableFutureTest : TestBase() {
415416
assertTrue(asDeferred.isCompleted)
416417
// By documentation, join() shouldn't throw when asDeferred is already complete.
417418
asDeferred.join()
418-
assertTrue(asDeferred.getCompletionExceptionOrNull() is CancellationException)
419+
assertIs<CancellationException>(asDeferred.getCompletionExceptionOrNull())
419420
}
420421

421422
@Test
@@ -443,13 +444,13 @@ class ListenableFutureTest : TestBase() {
443444
val deferred = future.asDeferred()
444445
assertTrue(deferred.isCancelled && deferred.isCompleted)
445446
val completionException = deferred.getCompletionExceptionOrNull()!!
446-
assertTrue(completionException is TestException)
447+
assertIs<TestException>(completionException)
447448

448449
try {
449450
deferred.await()
450451
expectUnreached()
451452
} catch (e: Throwable) {
452-
assertTrue(e is TestException)
453+
assertIs<TestException>(e)
453454
}
454455
}
455456

@@ -489,7 +490,7 @@ class ListenableFutureTest : TestBase() {
489490
future.asDeferred().await()
490491
expectUnreached()
491492
} catch (e: Throwable) {
492-
assertTrue(e is TestException)
493+
assertIs<TestException>(e)
493494
}
494495
}
495496

@@ -606,9 +607,9 @@ class ListenableFutureTest : TestBase() {
606607
val thrown = assertFailsWith<CancellationException> { future.get() }
607608
val cause = thrown.cause
608609
assertNotNull(cause)
609-
assertTrue(cause is CancellationException)
610+
assertIs<CancellationException>(cause)
610611
assertEquals("Parent cancelled", cause.message)
611-
assertTrue(cause.cause is TestException)
612+
assertIs<TestException>(cause.cause)
612613
finish(5)
613614
}
614615

@@ -703,7 +704,7 @@ class ListenableFutureTest : TestBase() {
703704
private inline fun <reified T: Throwable> ListenableFuture<*>.checkFutureException() {
704705
val e = assertFailsWith<ExecutionException> { get() }
705706
val cause = e.cause!!
706-
assertTrue(cause is T)
707+
assertIs<T>(cause)
707708
}
708709

709710
@Suppress("SuspendFunctionOnCoroutineScope")

integration/kotlinx-coroutines-guava/test/ListenableFutureToStringTest.kt

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package kotlinx.coroutines.guava
22

3+
import kotlinx.coroutines.testing.*
34
import kotlinx.coroutines.*
45
import org.junit.Test
56
import kotlin.test.*

integration/kotlinx-coroutines-play-services/test/TaskTest.kt

+16-14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package kotlinx.coroutines.tasks
22

3+
import kotlinx.coroutines.testing.*
34
import com.google.android.gms.tasks.*
45
import kotlinx.coroutines.*
56
import org.junit.*
@@ -50,7 +51,7 @@ class TaskTest : TestBase() {
5051
try {
5152
runTest { task.await() }
5253
} catch (e: Exception) {
53-
assertTrue(e is CancellationException)
54+
assertIs<CancellationException>(e)
5455
assertTrue(task.isCanceled)
5556
}
5657
}
@@ -102,7 +103,7 @@ class TaskTest : TestBase() {
102103
deferred.await()
103104
fail("deferred.await() should be cancelled")
104105
} catch (e: Exception) {
105-
assertTrue(e is CancellationException)
106+
assertIs<CancellationException>(e)
106107
}
107108
}
108109

@@ -112,14 +113,14 @@ class TaskTest : TestBase() {
112113

113114
assertTrue(deferred.isCancelled && deferred.isCompleted)
114115
val completionException = deferred.getCompletionExceptionOrNull()!!
115-
assertTrue(completionException is TestException)
116+
assertIs<TestException>(completionException)
116117
assertEquals("something went wrong", completionException.message)
117118

118119
try {
119120
deferred.await()
120121
fail("deferred.await() should throw an exception")
121122
} catch (e: Exception) {
122-
assertTrue(e is TestException)
123+
assertIs<TestException>(e)
123124
assertEquals("something went wrong", e.message)
124125
}
125126
}
@@ -139,7 +140,7 @@ class TaskTest : TestBase() {
139140
deferred.await()
140141
fail("deferred.await() should throw an exception")
141142
} catch (e: Exception) {
142-
assertTrue(e is TestException)
143+
assertIs<TestException>(e)
143144
assertEquals("something went wrong", e.message)
144145
assertSame(e.cause, deferred.getCompletionExceptionOrNull()) // debug mode stack augmentation
145146
}
@@ -170,7 +171,7 @@ class TaskTest : TestBase() {
170171
deferred.await()
171172
fail("deferred.await() should be cancelled")
172173
} catch (e: Exception) {
173-
assertTrue(e is CancellationException)
174+
assertIs<CancellationException>(e)
174175
}
175176
assertTrue(cancellationTokenSource.token.isCancellationRequested)
176177
}
@@ -186,7 +187,7 @@ class TaskTest : TestBase() {
186187
deferred.await()
187188
fail("deferred.await() should be cancelled")
188189
} catch (e: Exception) {
189-
assertTrue(e is CancellationException)
190+
assertIs<CancellationException>(e)
190191
}
191192
assertTrue(cancellationTokenSource.token.isCancellationRequested)
192193
}
@@ -203,7 +204,7 @@ class TaskTest : TestBase() {
203204
deferred.await()
204205
fail("deferred.await() should be cancelled")
205206
} catch (e: Exception) {
206-
assertTrue(e is CancellationException)
207+
assertIs<CancellationException>(e)
207208
}
208209
assertTrue(cancellationTokenSource.token.isCancellationRequested)
209210
}
@@ -222,18 +223,19 @@ class TaskTest : TestBase() {
222223
@Test
223224
fun testFailedCancellableTaskAsDeferred() = runTest {
224225
val cancellationTokenSource = CancellationTokenSource()
225-
val deferred = Tasks.forException<Int>(TestException("something went wrong")).asDeferred(cancellationTokenSource)
226+
val deferred =
227+
Tasks.forException<Int>(TestException("something went wrong")).asDeferred(cancellationTokenSource)
226228

227229
assertTrue(deferred.isCancelled && deferred.isCompleted)
228230
val completionException = deferred.getCompletionExceptionOrNull()!!
229-
assertTrue(completionException is TestException)
231+
assertIs<TestException>(completionException)
230232
assertEquals("something went wrong", completionException.message)
231233

232234
try {
233235
deferred.await()
234236
fail("deferred.await() should throw an exception")
235237
} catch (e: Exception) {
236-
assertTrue(e is TestException)
238+
assertIs<TestException>(e)
237239
assertEquals("something went wrong", e.message)
238240
}
239241
assertTrue(cancellationTokenSource.token.isCancellationRequested)
@@ -255,7 +257,7 @@ class TaskTest : TestBase() {
255257
deferred.await()
256258
fail("deferred.await() should throw an exception")
257259
} catch (e: Exception) {
258-
assertTrue(e is TestException)
260+
assertIs<TestException>(e)
259261
assertEquals("something went wrong", e.message)
260262
assertSame(e.cause, deferred.getCompletionExceptionOrNull()) // debug mode stack augmentation
261263
}
@@ -318,7 +320,7 @@ class TaskTest : TestBase() {
318320
deferred.await()
319321
fail("deferred.await() should be cancelled")
320322
} catch (e: Exception) {
321-
assertTrue(e is CancellationException)
323+
assertIs<CancellationException>(e)
322324
}
323325

324326
assertTrue(cancellationTokenSource.token.isCancellationRequested)
@@ -341,7 +343,7 @@ class TaskTest : TestBase() {
341343
deferred.await()
342344
fail("deferred.await() should be cancelled")
343345
} catch (e: Exception) {
344-
assertTrue(e is CancellationException)
346+
assertIs<CancellationException>(e)
345347
}
346348

347349
assertTrue(cancellationTokenSource.token.isCancellationRequested)

integration/kotlinx-coroutines-slf4j/test/MDCContextTest.kt

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package kotlinx.coroutines.slf4j
22

3+
import kotlinx.coroutines.testing.*
34
import kotlinx.coroutines.*
45
import org.junit.*
56
import org.junit.Test

kotlinx-coroutines-core/common/test/AbstractCoroutineTest.kt

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package kotlinx.coroutines
22

3+
import kotlinx.coroutines.testing.*
34
import kotlin.coroutines.*
45
import kotlin.test.*
56

@@ -55,7 +56,7 @@ class AbstractCoroutineTest : TestBase() {
5556
}
5657

5758
override fun onCancelling(cause: Throwable?) {
58-
assertTrue(cause is TestException1)
59+
assertIs<TestException1>(cause)
5960
expect(5)
6061
}
6162

@@ -64,18 +65,18 @@ class AbstractCoroutineTest : TestBase() {
6465
}
6566

6667
override fun onCancelled(cause: Throwable, handled: Boolean) {
67-
assertTrue(cause is TestException1)
68+
assertIs<TestException1>(cause)
6869
expect(8)
6970
}
7071
}
7172

7273
coroutine.invokeOnCompletion(onCancelling = true) {
73-
assertTrue(it is TestException1)
74+
assertIs<TestException1>(it)
7475
expect(6)
7576
}
7677

7778
coroutine.invokeOnCompletion {
78-
assertTrue(it is TestException1)
79+
assertIs<TestException1>(it)
7980
expect(9)
8081
}
8182

kotlinx-coroutines-core/common/test/AsyncLazyTest.kt

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
package kotlinx.coroutines
44

5+
import kotlinx.coroutines.testing.*
56
import kotlin.test.*
67

78
class AsyncLazyTest : TestBase() {

0 commit comments

Comments
 (0)