Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking change: explicitly import either asyncdispatch or chronos #11

Merged
merged 4 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 28 additions & 18 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,29 @@ requires "asynctest >= 0.4.3 & < 0.5.0"
Usage
-----

Simply replace `import unittest` with `import asynctest`, and you can await
Replace `import unittest` with one of the following imports, and you can await
asynchronous calls in tests, setup and teardown.

When you use Nim's standard library only ([asyncdispatch][4] and [unittest][1]):
```nim
import asynctest/asyncdispatch/unittest
```

When you use [chronos][5] or [unittest2][3], pick the import that matches your
choices:

```nim
import asynctest/asyncdispatch/unittest2 # standard async and unittest2
import asynctest/chronos/unittest # chronos and standard unittest
import asynctest/chronos/unittest2 # chronos and unittest2
```

Example
-------

```nim

import asynctest
import asyncdispatch # alternatively: import chronos
import asynctest/asyncdispatch/unittest

proc someAsyncProc {.async.} =
# perform some async operations using await
Expand All @@ -47,17 +60,6 @@ suite "test async proc":

```

setupAll and teardownAll
------------------------

The `setup` and `teardown` code runs before and after every test, just like the
standard [unittest][1] module. In addition we provide `setupAll` and
`teardownAll`. The `setupAll` code runs once before all tests in the suite, and
the `teardownAll` runs once after all tests in the suite. Use these only as a
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
----------------

Expand All @@ -78,12 +80,20 @@ check eventually x == 42
await future
```

Unittest2
---------
setupAll and teardownAll
------------------------

The `setup` and `teardown` code runs before and after every test, just like the
standard [unittest][1] module. In addition we provide `setupAll` and
`teardownAll`. The `setupAll` code runs once before all tests in the suite, and
the `teardownAll` runs once after all tests in the suite. Use these only as a
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.

The [unittest2][3] package is supported. Make sure that you
`import asynctest/unittest2` instead of the normal import.

[1]: https://nim-lang.org/docs/unittest.html
[2]: https://github.com/nim-lang/nimble
[3]: https://github.com/status-im/nim-unittest2
[4]: https://nim-lang.org/docs/asyncdispatch.html
[5]: https://github.com/status-im/nim-chronos/
7 changes: 4 additions & 3 deletions asynctest.nim
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ./asynctest/unittest

export unittest
{.error:
"As of version 0.5.0 you need to import either " &
"asynctest/asyncdispatch/unittest or " &
"asynctest/chronos/unittest depending on your choice of async framework".}
10 changes: 10 additions & 0 deletions asynctest/asyncdispatch/unittest.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import std/asyncdispatch
import std/unittest
import ../private/asyncdispatch/eventually
import ../private/asyncdispatch/runasync

export asyncdispatch
export unittest except suite, test
export eventually

include ../private/suite
10 changes: 10 additions & 0 deletions asynctest/asyncdispatch/unittest2.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import std/asyncdispatch
import pkg/unittest2
import ../private/asyncdispatch/eventually
import ../private/asyncdispatch/runasync

export asyncdispatch
export unittest2 except suite, test
export eventually

include ../private/suite
10 changes: 10 additions & 0 deletions asynctest/chronos/unittest.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import pkg/chronos
import std/unittest
import ../private/chronos/eventually
import ../private/chronos/unittest/runasync

export chronos
export unittest except suite, test
export eventually

include ../private/suite
10 changes: 10 additions & 0 deletions asynctest/chronos/unittest2.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import pkg/chronos
import pkg/unittest2
import ../private/chronos/eventually
import ../private/chronos/unittest2/runasync

export chronos
export unittest2 except suite, test
export eventually

include ../private/suite
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import std/times except milliseconds
import std/asyncdispatch
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)
await sleepAsync(10)
return true

await eventually()
5 changes: 5 additions & 0 deletions asynctest/private/asyncdispatch/runasync.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import std/asyncdispatch

template runAsync*(body): untyped =
let asyncProc = proc {.async.} = body
waitFor asyncProc()
13 changes: 13 additions & 0 deletions asynctest/private/chronos/eventually.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import pkg/chronos

template eventually*(expression: untyped, timeout=5000): bool =

proc eventually: Future[bool] {.async.} =
let endTime = Moment.now() + timeout.milliseconds
while not expression:
if endTime < Moment.now():
return false
await sleepAsync(10.milliseconds)
return true

await eventually()
21 changes: 21 additions & 0 deletions asynctest/private/chronos/unittest/runasync.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import pkg/chronos
import pkg/chronos/config

when compiles(config.chronosHandleException): # detect chronos v4

template runAsync*(body): untyped =
# The unittest module from stdlib can still raise a bare Exception,
# so we allow chronos to convert it to an AsyncExceptionError, and
# we disable the ensuing BareExcept warning.
{.push warning[BareExcept]:off.}
let asyncProc =
proc {.async: (handleException: true, raises: [AsyncExceptionError]).} =
body
{.pop.}
waitFor asyncProc()

else:

template runAsync*(body): untyped =
let asyncProc = proc {.async.} = body
waitFor asyncProc()
5 changes: 5 additions & 0 deletions asynctest/private/chronos/unittest2/runasync.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import pkg/chronos

template runAsync*(body): untyped =
let asyncProc = proc {.async.} = body
waitFor asyncProc()
34 changes: 34 additions & 0 deletions asynctest/private/suite.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
template suite*(name, body) =

suite name:
let suiteproc = proc =

## Runs before all tests in the suite
template setupAll(setupAllBody) {.used.} =
runAsync setupAllBody

## Runs after all tests in the suite
template teardownAll(teardownAllBody) {.used.} =
template teardownAllIMPL: untyped {.inject.} =
runAsync teardownAllBody

template setup(setupBody) {.used.} =
setup:
runAsync setupBody

template teardown(teardownBody) {.used.} =
teardown:
let exception = getCurrentException()
runAsync teardownBody
setCurrentException(exception)

body

when declared(teardownAllIMPL):
teardownAllIMPL()

suiteproc()

template test*(name, body) =
test name:
runAsync body
58 changes: 0 additions & 58 deletions asynctest/templates.nim

This file was deleted.

7 changes: 0 additions & 7 deletions asynctest/unittest.nim

This file was deleted.

11 changes: 4 additions & 7 deletions asynctest/unittest2.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import pkg/unittest2
import ./eventually

export unittest2 except suite, test
export eventually

include ./templates
{.error:
"As of version 0.5.0 you need to import either " &
"asynctest/asyncdispatch/unittest2 or " &
"asynctest/chronos/unittest2 depending on your choice of async framework".}
7 changes: 3 additions & 4 deletions testmodules/chronosv3/test.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import pkg/asynctest
import pkg/chronos
import pkg/asynctest/chronos/unittest

include ../stdlib/testbody
include ../stdlib/testfail
include ../common/testbody
include ../common/testfail
7 changes: 3 additions & 4 deletions testmodules/chronosv4/test.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import pkg/asynctest
import pkg/chronos
import pkg/asynctest/chronos/unittest

include ../stdlib/testbody
include ../stdlib/testfail
include ../common/testbody
include ../common/testfail
File renamed without changes.
File renamed without changes.
7 changes: 3 additions & 4 deletions testmodules/stdlib/test.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import std/asyncdispatch
import pkg/asynctest
import pkg/asynctest/asyncdispatch/unittest

include ./testbody
include ./testfail
include ../common/testbody
include ../common/testfail
7 changes: 3 additions & 4 deletions testmodules/unittest2/test.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import pkg/asynctest/unittest2
import pkg/chronos
import pkg/asynctest/asyncdispatch/unittest2

include ../stdlib/testbody
include ../stdlib/testfail
include ../common/testbody
include ../common/testfail
Loading