Skip to content

Commit 445e798

Browse files
committed
Knitted links and fixed minor style issues in test docs readme
1 parent c0a8d1c commit 445e798

File tree

1 file changed

+44
-40
lines changed

1 file changed

+44
-40
lines changed

kotlinx-coroutines-test/README.md

+44-40
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ dependencies {
1616
**Do not** depend on this project in your main sources, all utilities are intended and designed to be used only from tests.
1717

1818
## Dispatchers.Main Delegation
19+
1920
`Dispatchers.setMain` will override the `Main` dispatcher in test situations. This is helpful when you want to execute a
2021
test in situations where the platform `Main` dispatcher is not available, or you wish to replace `Dispatchers.Main` with a
2122
testing dispatcher.
@@ -46,7 +47,7 @@ class SomeTest {
4647
@Test
4748
fun testSomeUI() = runBlocking {
4849
launch(Dispatchers.Main) { // Will be launched in the mainThreadSurrogate dispatcher
49-
...
50+
// ...
5051
}
5152
}
5253
}
@@ -66,19 +67,20 @@ builder that provides extra test control to coroutines.
6667
5. Report uncaught exceptions as test failures
6768

6869
### Testing regular suspend functions
70+
6971
To test regular suspend functions, which may have a delay, you can use the [runBlockingTest] builder to start a testing
7072
coroutine. Any calls to `delay` will automatically advance time.
7173

7274
```kotlin
7375
@Test
7476
fun testFoo() = runBlockingTest { // a coroutine with a extra test control
7577
val actual = foo()
76-
...
78+
// ...
7779
}
7880

7981
suspend fun foo() {
8082
delay(1_000) // auto-advances without delay due to runBlockingTest
81-
...
83+
// ...
8284
}
8385
```
8486

@@ -94,10 +96,10 @@ the first [delay].
9496

9597
```kotlin
9698
@Test
97-
fun testFoo_withLaunch() = runBlockingTest {
99+
fun testFooWithLaunch() = runBlockingTest {
98100
foo()
99101
// the coroutine launched by foo() is completed before foo() returns
100-
...
102+
// ...
101103
}
102104

103105
fun CoroutineScope.foo() {
@@ -124,12 +126,12 @@ To control time in the test you can use the [DelayController] interface. The blo
124126

125127
```kotlin
126128
@Test
127-
fun testFoo_withLaunch_andDelay() = runBlockingTest {
129+
fun testFooWithLaunchAndDelay() = runBlockingTest {
128130
foo()
129131
// the coroutine launched by foo has not completed here, it is suspended waiting for delay(1_000)
130132
advanceTimeBy(1_000) // progress time, this will cause the delay to resume
131133
// foo() coroutine launched by foo has completed here
132-
...
134+
// ...
133135
}
134136

135137
suspend fun CoroutineScope.foo() {
@@ -142,7 +144,8 @@ suspend fun CoroutineScope.foo() {
142144
```
143145

144146
*Note:* `runBlockingTest` will always attempt to auto-progress time until all coroutines are completed just before
145-
exiting. This is a convenience to avoid having to call [advanceUntilIdle] as the last line of many common test cases.
147+
exiting. This is a convenience to avoid having to call [advanceUntilIdle][DelayController.advanceUntilIdle]
148+
as the last line of many common test cases.
146149
If any coroutines cannot complete by advancing time, a [UncompletedCoroutinesError] is thrown.
147150

148151
### Testing `withTimeout` using `runBlockingTest`
@@ -155,18 +158,18 @@ example an uncompleted `Deferred<Foo>` is provided to the function under test vi
155158

156159
```kotlin
157160
@Test(expected = TimeoutCancellationException::class)
158-
fun testFoo_withTimeout() {
161+
fun testFooWithTimeout() {
159162
val uncompleted = CompletableDeferred<Foo>() // this Deferred<Foo> will never complete
160163
foo(uncompleted)
161164
advanceTimeBy(1_000) // advance time, which will cause the timeout to throw an exception
162-
...
165+
// ...
163166
}
164167

165168
fun CoroutineScope.foo(resultDeferred: Deferred<Foo>) {
166169
launch {
167170
withTimeout(1_000) {
168171
resultDeferred.await() // await() will suspend forever waiting for uncompleted
169-
...
172+
// ...
170173
}
171174
}
172175
}
@@ -181,15 +184,15 @@ create a second coroutine.
181184
The eager execution of `launch` and `async` bodies makes many tests easier, but some tests need more fine grained
182185
control of coroutine execution.
183186

184-
To disable eager execution, you can call [pauseDispatcher] to pause the [TestCoroutineDispatcher] that [runBlockingTest]
185-
uses.
187+
To disable eager execution, you can call [pauseDispatcher][DelayController.pauseDispatcher]
188+
to pause the [TestCoroutineDispatcher] that [runBlockingTest] uses.
186189

187190
When the dispatcher is paused, all coroutines will be added to a queue instead running. In addition, time will never
188191
auto-progress due to `delay` on a paused dispatcher.
189192

190193
```kotlin
191194
@Test
192-
fun testFoo_withPauseDispatcher() = runBlockingTest {
195+
fun testFooWithPauseDispatcher() = runBlockingTest {
193196
pauseDispatcher {
194197
foo()
195198
// the coroutine started by foo has not run yet
@@ -198,7 +201,7 @@ fun testFoo_withPauseDispatcher() = runBlockingTest {
198201
advanceTimeBy(1_000) // progress time, this will cause the delay to resume
199202
// the coroutine started by foo has called println(2) and has completed here
200203
}
201-
...
204+
// ...
202205
}
203206

204207
fun CoroutineScope.foo() {
@@ -216,8 +219,8 @@ non-trivial external dependencies and side effects in their launch body.
216219

217220
*Important:* When passed a lambda block, `pauseDispatcher` will resume eager execution immediately after the block.
218221
This will cause time to auto-progress if there are any outstanding `delay` calls that were not resolved before the
219-
`pauseDispatcher` block returned. In advanced situations tests can call [pauseDispatcher][pausedispatcher.noarg] without a lambda block and
220-
then explicitly resume the dispatcher with [resumeDispatcher].
222+
`pauseDispatcher` block returned. In advanced situations tests can call [pauseDispatcher][DelayController.pauseDispatcher]
223+
without a lambda block and then explicitly resume the dispatcher with [resumeDispatcher][DelayController.resumeDispatcher].
221224

222225
## Integrating tests with structured concurrency
223226

@@ -241,6 +244,7 @@ By providing [TestCoroutineScope] a test case is able to control execution of co
241244
uncaught exceptions thrown by coroutines are converted into test failures.
242245

243246
### Providing `TestCoroutineScope` from `runBlockingTest`
247+
244248
In simple cases, tests can use the [TestCoroutineScope] created by [runBlockingTest] directly.
245249

246250
```kotlin
@@ -251,21 +255,22 @@ fun testFoo() = runBlockingTest {
251255

252256
fun CoroutineScope.foo() {
253257
launch { // CoroutineScope for launch is the TestCoroutineScope provided by runBlockingTest
254-
...
258+
// ...
255259
}
256260
}
257261
```
258262

259263
This style is preferred when the `CoroutineScope` is passed through an extension function style.
260264

261265
### Providing an explicit `TestCoroutineScope`
266+
262267
In many cases, the direct style is not preferred because [CoroutineScope] may need to be provided through anther means
263268
such as dependency injection or service locators.
264269

265270
Tests can declare a [TestCoroutineScope] explicitly in the class to support these use cases.
266271

267272
Since [TestCoroutineScope] is stateful in order to keep track of executing coroutines and uncaught exceptions, it is
268-
important to ensure that [cleanupTestCoroutines][cleanupTestCoroutines.scope] is called after every test case.
273+
important to ensure that [cleanupTestCoroutines][TestCoroutineScope.cleanupTestCoroutines] is called after every test case.
269274

270275
```kotlin
271276
class TestClass {
@@ -304,6 +309,7 @@ test libraries to provide library specific integrations. For example, a JUnit4 `
304309
[Dispatchers.setMain][setMain] then expose [TestCoroutineScope] for use in tests.
305310

306311
### Providing an explicit `TestCoroutineDispatcher`
312+
307313
While providing a [TestCoroutineScope] is slightly preferred due to the improved uncaught exception handling, there are
308314
many situations where it is easier to provide a [TestCoroutineDispatcher]. For example [Dispatchers.setMain][setMain]
309315
does not accept a [TestCoroutineScope] and requires a [TestCoroutineDispatcher] to control coroutine execution in
@@ -319,7 +325,7 @@ when the class under test allows a test to provide a [CoroutineDispatcher] but d
319325
[CoroutineScope].
320326

321327
Since [TestCoroutineDispatcher] is stateful in order to keep track of executing coroutines, it is
322-
important to ensure that [cleanupTestCoroutines][cleanupTestCoroutines.dispatcher] is called after every test case.
328+
important to ensure that [cleanupTestCoroutines][TestCoroutineDispatcher.cleanupTestCoroutines] is called after every test case.
323329

324330
```kotlin
325331
class TestClass {
@@ -363,7 +369,7 @@ this to provide alternatives to `runBlockingTest`.
363369

364370
```kotlin
365371
@Test
366-
fun testFoo_withAutoProgress() {
372+
fun testFooWithAutoProgress() {
367373
val scope = TestCoroutineScope()
368374
scope.foo()
369375
// foo is suspended waiting for time to progress
@@ -381,6 +387,7 @@ fun CoroutineScope.foo() {
381387
```
382388

383389
## Using time control with `withContext`
390+
384391
Calls to `withContext(Dispatchers.IO)` or `withContext(Dispatchers.Default)` are common in coroutines based codebases.
385392
Both dispatchers are not designed to interact with `TestCoroutineDispatcher`.
386393

@@ -413,37 +420,34 @@ delays, or when execution control is needed to test complex logic.
413420
### Status of the API
414421

415422
This API is experimental and it is may change before migrating out of experimental (while it is marked as
416-
`@ExperimentalCoroutinesApi`). Changes during experimental may have deprecation applied when possible, but it is not
417-
advised to use the API before it leaves experimental due to possible breaking changes.
423+
[`@ExperimentalCoroutinesApi`][ExperimentalCoroutinesApi]).
424+
Changes during experimental may have deprecation applied when possible, but it is not
425+
advised to use the API in stable code before it leaves experimental due to possible breaking changes.
418426

419427
If you have any suggestions for improvements to this experimental API please share them them on the
420428
[issue tracker](https://github.com/Kotlin/kotlinx.coroutines/issues).
421429

422-
423430
<!--- MODULE kotlinx-coroutines-core -->
424431
<!--- INDEX kotlinx.coroutines -->
425432
[Dispatchers.Main]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-dispatchers/-main.html
426433
[CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-dispatcher/index.html
427-
[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/
428434
[launch]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html
429435
[async]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/async.html
430436
[delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/delay.html
437+
[CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-coroutine-scope/index.html
438+
[ExperimentalCoroutinesApi]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/-experimental-coroutines-api/index.html
431439
<!--- MODULE kotlinx-coroutines-test -->
432440
<!--- INDEX kotlinx.coroutines.test -->
433441
[setMain]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/kotlinx.coroutines.-dispatchers/set-main.html
434-
435-
[runBlockingTest]: https://notapage/
436-
[UncompletedCoroutinesError]: https://notapage/
437-
[DelayController]: https://notapage/
438-
[pauseDispatcher]: https://notapage/
439-
[pauseDispatcher.noarg]: https://notapage/noarg
440-
[resumeDispatcher]: https://notapage/
441-
[advanceUntilIdle]: https://notapage/
442-
[advanceTimeBy]: https://notapage/
443-
[resumeDispatcher]: https://notapage/
444-
[TestCoroutineDispatcher]: https://notapage/
445-
[TestCoroutineExceptionHandler]: https://notapage/
446-
[TestCoroutineScope]: https://notapage/
447-
[cleanupTestCoroutines.scope]: https://notapage/cleanupscope
448-
[cleanupTestCoroutines.dispatcher]: https://notapage/cleanupdispatcher
442+
[runBlockingTest]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/run-blocking-test.html
443+
[UncompletedCoroutinesError]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-uncompleted-coroutines-error/index.html
444+
[DelayController]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-delay-controller/index.html
445+
[DelayController.advanceUntilIdle]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-delay-controller/advance-until-idle.html
446+
[DelayController.pauseDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-delay-controller/pause-dispatcher.html
447+
[TestCoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-test-coroutine-dispatcher/index.html
448+
[DelayController.resumeDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-delay-controller/resume-dispatcher.html
449+
[TestCoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-test-coroutine-scope/index.html
450+
[TestCoroutineExceptionHandler]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-test-coroutine-exception-handler/index.html
451+
[TestCoroutineScope.cleanupTestCoroutines]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-test-coroutine-scope/cleanup-test-coroutines.html
452+
[TestCoroutineDispatcher.cleanupTestCoroutines]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-test-coroutine-dispatcher/cleanup-test-coroutines.html
449453
<!--- END -->

0 commit comments

Comments
 (0)