Add `eventually` to wait for a condition to become true
This commit is contained in:
parent
a236a5f0f3
commit
c8d324cfa6
20
Readme.md
20
Readme.md
|
@ -58,6 +58,26 @@ last resort when setting up the test environment is very costly. Be careful that
|
|||
the tests do not modify the environment that you set up, lest you introduce
|
||||
dependencies between tests.
|
||||
|
||||
check eventually
|
||||
----------------
|
||||
|
||||
When you find yourself adding calls to `sleepAsync` to your tests, you might
|
||||
want to consider using `check eventually` instead. It will repeatedly check
|
||||
an expression until it becomes true. It has a built-in timeout of 5 seconds that
|
||||
you can override.
|
||||
|
||||
```nim
|
||||
var x: int
|
||||
|
||||
proc slowProcedure {.async.} =
|
||||
# perform a slow operation
|
||||
x = 42
|
||||
|
||||
let future = slowProcedure()
|
||||
check eventually x == 42
|
||||
await future
|
||||
```
|
||||
|
||||
Unittest2
|
||||
---------
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
import std/times
|
||||
|
||||
template eventually*(expression: untyped, timeout=5000): bool =
|
||||
|
||||
template sleep(millis: int): auto =
|
||||
when compiles(await sleepAsync(millis.milliseconds)):
|
||||
sleepAsync(millis.milliseconds) # chronos
|
||||
else:
|
||||
sleepAsync(millis) # asyncdispatch
|
||||
|
||||
proc eventually: Future[bool] {.async.} =
|
||||
let endTime = getTime() + initDuration(milliseconds=timeout)
|
||||
while not expression:
|
||||
if endTime < getTime():
|
||||
return false
|
||||
await sleep(10)
|
||||
return true
|
||||
|
||||
await eventually()
|
|
@ -1,4 +1,7 @@
|
|||
import std/unittest
|
||||
import ./eventually
|
||||
|
||||
export unittest except suite, test
|
||||
export eventually
|
||||
|
||||
include ./templates
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import pkg/unittest2
|
||||
import ./eventually
|
||||
|
||||
export unittest2 except suite, test
|
||||
export eventually
|
||||
|
||||
include ./templates
|
||||
|
|
|
@ -16,7 +16,7 @@ suite "test async proc":
|
|||
# invoke await in tests:
|
||||
await someAsyncProc()
|
||||
|
||||
suite "test async setupAll and teardownAll, allow multiple suites":
|
||||
suite "setupAll and teardownAll":
|
||||
|
||||
setupAll:
|
||||
# invoke await in the test setup:
|
||||
|
@ -29,3 +29,46 @@ suite "test async setupAll and teardownAll, allow multiple suites":
|
|||
test "async test":
|
||||
# invoke await in tests:
|
||||
await someAsyncProc()
|
||||
|
||||
from std/os import sleep
|
||||
|
||||
suite "eventually":
|
||||
|
||||
test "becomes true":
|
||||
|
||||
var tries = 0
|
||||
|
||||
proc becomesTrue: bool =
|
||||
inc tries
|
||||
tries == 3
|
||||
|
||||
check eventually becomesTrue()
|
||||
|
||||
test "becomes false after timeout":
|
||||
|
||||
proc remainsFalse: bool = false
|
||||
|
||||
check not eventually(remainsFalse(), timeout=100)
|
||||
|
||||
test "becomes true during timeout":
|
||||
|
||||
proc slowTrue: bool =
|
||||
sleep(100)
|
||||
true
|
||||
|
||||
check eventually(slowTrue(), timeout=50)
|
||||
|
||||
test "works with async procedures":
|
||||
|
||||
var x: int
|
||||
|
||||
proc slowProcedure {.async.} =
|
||||
when compiles(await sleepAsync(100.milliseconds)):
|
||||
await sleepAsync(100.milliseconds) # chronos
|
||||
else:
|
||||
await sleepAsync(100) # asyncdispatch
|
||||
x = 42
|
||||
|
||||
let future = slowProcedure()
|
||||
check eventually x == 42
|
||||
await future
|
||||
|
|
Loading…
Reference in New Issue