diff --git a/Readme.md b/Readme.md index 6806237..f8ba228 100644 --- a/Readme.md +++ b/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 --------- diff --git a/asynctest/eventually.nim b/asynctest/eventually.nim new file mode 100644 index 0000000..1265b9e --- /dev/null +++ b/asynctest/eventually.nim @@ -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() diff --git a/asynctest/unittest.nim b/asynctest/unittest.nim index 216f53b..8efbf33 100644 --- a/asynctest/unittest.nim +++ b/asynctest/unittest.nim @@ -1,4 +1,7 @@ import std/unittest +import ./eventually + export unittest except suite, test +export eventually include ./templates diff --git a/asynctest/unittest2.nim b/asynctest/unittest2.nim index ce1d1ef..67ad9cb 100644 --- a/asynctest/unittest2.nim +++ b/asynctest/unittest2.nim @@ -1,4 +1,7 @@ import pkg/unittest2 +import ./eventually + export unittest2 except suite, test +export eventually include ./templates diff --git a/testmodules/stdlib/testbody.nim b/testmodules/stdlib/testbody.nim index b3a8ca0..1c4f725 100644 --- a/testmodules/stdlib/testbody.nim +++ b/testmodules/stdlib/testbody.nim @@ -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