asynctest documentation¶
The package asynctest is built on top of the standard unittest
module
and cuts down boilerplate code when testing libraries for asyncio
.
asynctest imports the standard unittest package, overrides some of its features
and adds new ones. A test author can import asynctest in place of
unittest
safely.
It is divided in submodules, but they are all imported at the top level,
so asynctest.case.TestCase
is equivalent to asynctest.TestCase
.
Currently, asynctest targets the “selector” model. Hence, some features will not (yet) work with Windows’ proactor.
This documentation contains the reference of the classes and functions defined by asynctest, and an introduction guide.
Reference¶
Module asynctest.case¶
Enhance unittest.TestCase
:
- a new loop is issued and set as the default loop before each test, and closed and disposed after,
- if the loop uses a selector, it will be wrapped with
asynctest.TestSelector
, - a test method in a TestCase identified as a coroutine function or returning a coroutine will run on the loop,
setUp()
andtearDown()
methods can be coroutine functions,- cleanup functions registered with
addCleanup()
can be coroutine functions, - a test fails if the loop did not run during the test.
class-level set-up¶
Since each test runs in its own loop, it is not possible to run
setUpClass()
and tearDownClass()
as
coroutines.
If one needs to perform set-up actions at the class level (meaning once for all tests in the class), it should be done using a loop created for this sole purpose and that is not shared with the tests. Ideally, the loop shall be closed in the method which creates it.
If one really needs to share a loop between tests,
TestCase.use_default_loop
can be set to True
(as a class
attribute). The test case will use the loop returned by
asyncio.get_event_loop()
instead of creating a new loop for each test.
This way, the event loop or event loop policy can be set during class-level
set-up and tear down.
TestCases¶
-
class
asynctest.
TestCase
(methodName='runTest')[source]¶ A test which is a coroutine function or which returns a coroutine will run on the loop.
Once the test returned, one or more assertions are checked. For instance, a test fails if the loop didn’t run. These checks can be enabled or disabled using the
fail_on()
decorator.By default, a new loop is created and is set as the default loop before each test. Test authors can retrieve this loop with
loop
.If
use_default_loop
is set toTrue
, the current default event loop is used instead. In this case, it is up to the test author to deal with the state of the loop in each test: the loop might be closed, callbacks and tasks may be scheduled by previous tests. It is also up to the test author to close the loop and dispose the related resources.If
forbid_get_event_loop
is set toTrue
, a call toasyncio.get_event_loop()
will raise anAssertionError
. Since Python 3.6, callingasyncio.get_event_loop()
from a callback or a coroutine will return the running loop (instead of raising an exception).These behaviors should be configured when defining the test case class:
class With_Reusable_Loop_TestCase(asynctest.TestCase): use_default_loop = True forbid_get_event_loop = False def test_something(self): pass
If
setUp()
andtearDown()
are coroutine functions, they will run on the loop. Note thatsetUpClass()
andtearDownClass()
can not be coroutines.New in version 0.5: attribute
use_default_loop
.New in version 0.7: attribute
forbid_get_event_loop
. In any case, the default loop is now reset to its original state outside a test function.New in version 0.8:
ignore_loop
has been deprecated in favor of the extensiblefail_on()
decorator.-
tearDown
()[source]¶ Method called immediately after the test method has been called and the result recorded.
-
addCleanup
(function, *args, **kwargs)[source]¶ Add a function, with arguments, to be called when the test is completed. If function is a coroutine function, it will run on the loop before it’s cleaned.
-
assertAsyncRaises
(exception, awaitable)[source]¶ Test that an exception of type
exception
is raised when an exception is raised when awaitingawaitable
, a future or coroutine.See: unittest.TestCase.assertRaises()
-
assertAsyncRaisesRegex
(exception, regex, awaitable)[source]¶ Like
assertAsyncRaises()
but also tests thatregex
matches on the string representation of the raised exception.See: unittest.TestCase.assertRaisesRegex()
-
assertAsyncWarns
(warning, awaitable)[source]¶ Test that a warning is triggered when awaiting
awaitable
, a future or a coroutine.See: unittest.TestCase.assertWarns()
-
assertAsyncWarnsRegex
(warning, regex, awaitable)[source]¶ Like
assertAsyncWarns()
but also tests thatregex
matches on the message of the triggered warning.See: unittest.TestCase.assertWarnsRegex()
-
forbid_get_event_loop
= False¶ If true, the value returned by
asyncio.get_event_loop()
will be set toNone
during the test. It allows to ensure that tested code use a loop object explicitly passed around.
-
loop
= None¶ Event loop created and set as default event loop during the test.
-
use_default_loop
= False¶ If true, the loop used by the test case is the current default event loop returned by
asyncio.get_event_loop()
. The loop will not be closed and recreated between tests.
-
-
class
asynctest.
FunctionTestCase
(testFunc, setUp=None, tearDown=None, description=None)[source]¶ Enables the same features as
TestCase
, but forFunctionTestCase
.
-
class
asynctest.
ClockedTestCase
(methodName='runTest')[source]¶ Subclass of
TestCase
with a controlled loop clock, useful for testing timer based behaviour without slowing test run time.-
advance
(seconds)[source]¶ Fast forward time by a number of
seconds
.Callbacks scheduled to run up to the destination clock time will be executed on time:
>>> self.loop.call_later(1, print_time) >>> self.loop.call_later(2, self.loop.call_later, 1, print_time) >>> await self.advance(3) 1 3
In this example, the third callback is scheduled at
t = 2
to be executed att + 1
. Hence, it will run att = 3
. The callback as been called on time.
-
Decorators¶
-
@
asynctest.
fail_on
(**checks)¶ Enable checks on the loop state after a test ran to help testers to identify common mistakes.
Enable or disable a check using a keywork argument with a boolean value:
@asynctest.fail_on(unused_loop=True) class TestCase(asynctest.TestCase): ...
Available checks are:
unused_loop
: disabled by default, checks that the loop ran at least once during the test. This check can not fail if the test method is a coroutine. This allows to detect cases where a test author assume its test will run tasks or callbacks on the loop, but it actually didn’t.active_selector_callbacks
: enabled by default, checks that any registered reader or writer callback on a selector loop (withadd_reader()
oradd_writer()
) is later explicitly unregistered (withremove_reader()
orremove_writer()
) before the end of the test.active_handles
: disabled by default, checks that there is not scheduled callback left to be executed on the loop at the end of the test. The helperexhaust_callbacks()
can help to give a chance to the loop to run pending callbacks.
The decorator of a method has a greater priority than the decorator of a class. When
fail_on()
decorates a class and one of its methods with conflicting arguments, those of the class are overriden.Subclasses of a decorated
TestCase
inherit of the checks enabled on the parent class.New in version 0.8.
New in version 0.9:
active_handles
New in version 0.12:
unused_loop
is now deactivated by default to maintain compatibility with non-async test inherited fromunittest.TestCase
. This check is especially useful to track missing@asyncio.coroutine
decorators in a codebase that must be compatbible with Python 3.4.
-
@
asynctest.case.
strict
¶ Activate strict checking of the state of the loop after a test ran.
It is a shortcut to
fail_on()
with all checks set toTrue
.Note that by definition, the behavior of
strict()
will change in the future when new checks will be added, and may break existing tests with new errors after an update of the library.New in version 0.8.
-
@
asynctest.case.
lenient
¶ Deactivate all checks performed after a test ran.
It is a shortcut to
fail_on()
with all checks set toFalse
.New in version 0.8.
-
@
asynctest.
ignore_loop
¶ By default, a test fails if the loop did not run during the test (including set up and tear down), unless the
TestCase
class or test function is decorated byignore_loop()
.Deprecated since version 0.8: Use
fail_on()
withunused_loop=False
instead.
Mock objects¶
Wrapper to unittest.mock reducing the boilerplate when testing asyncio powered code.
A mock can behave as a coroutine, as specified in the documentation of
Mock
.
Mock classes¶
-
class
asynctest.
Mock
(spec=None, side_effect=None, return_value=sentinel.DEFAULT, wraps=None, name=None, spec_set=None, parent=None, _spec_state=None, _new_name='', _new_parent=None, **kwargs)[source]¶ Enhance
unittest.mock.Mock
so it returns aCoroutineMock
object instead of aMock
object where a method on aspec
orspec_set
object is a coroutine.For instance:
>>> class Foo: ... @asyncio.coroutine ... def foo(self): ... pass ... ... def bar(self): ... pass
>>> type(asynctest.mock.Mock(Foo()).foo) <class 'asynctest.mock.CoroutineMock'>
>>> type(asynctest.mock.Mock(Foo()).bar) <class 'asynctest.mock.Mock'>
The test author can also specify a wrapped object with
wraps
. In this case, theMock
object behavior is the same as with anunittest.mock.Mock
object: the wrapped object may have methods defined as coroutine functions.If you want to mock a coroutine function, use
CoroutineMock
instead.See
NonCallableMock
for details aboutasynctest
features, andunittest.mock
for the comprehensive documentation about mocking.
-
class
asynctest.
NonCallableMock
(spec=None, wraps=None, name=None, spec_set=None, is_coroutine=None, parent=None, **kwargs)[source]¶ Enhance
unittest.mock.NonCallableMock
with features allowing to mock a coroutine function.If
is_coroutine
is set toTrue
, theNonCallableMock
object will behave soasyncio.iscoroutinefunction()
will returnTrue
withmock
as parameter.If
spec
orspec_set
is defined and an attribute is get,CoroutineMock
is returned instead ofMock
when the matching spec attribute is a coroutine function.The test author can also specify a wrapped object with
wraps
. In this case, theMock
object behavior is the same as with anunittest.mock.Mock
object: the wrapped object may have methods defined as coroutine functions.See
unittest.mock.NonCallableMock
-
is_coroutine
¶ True if the object mocked is a coroutine
-
-
class
asynctest.
MagicMock
(*args, **kwargs)[source]¶ Enhance
unittest.mock.MagicMock
so it returns aCoroutineMock
object instead of aMock
object where a method on aspec
orspec_set
object is a coroutine.If you want to mock a coroutine function, use
CoroutineMock
instead.MagicMock
allows to mock__aenter__
,__aexit__
,__aiter__
and__anext__
.When mocking an asynchronous iterator, you can set the
return_value
of__aiter__
to an iterable to define the list of values to be returned during iteration.You can not mock
__await__
. If you want to mock an object implementing __await__,CoroutineMock
will likely be sufficient.see
Mock
.New in version 0.11: support of asynchronous iterators and asynchronous context managers.
-
class
asynctest.
CoroutineMock
(*args, **kwargs)[source]¶ Enhance
Mock
with features allowing to mock a coroutine function.The
CoroutineMock
object will behave so the object is recognized as coroutine function, and the result of a call as a coroutine:>>> mock = CoroutineMock() >>> asyncio.iscoroutinefunction(mock) True >>> asyncio.iscoroutine(mock()) True
The result of
mock()
is a coroutine which will have the outcome ofside_effect
orreturn_value
:- if
side_effect
is a function, the coroutine will return the result of that function, - if
side_effect
is an exception, the coroutine will raise the exception, - if
side_effect
is an iterable, the coroutine will return the next value of the iterable, however, if the sequence of result is exhausted,StopIteration
is raised immediately, - if
side_effect
is not defined, the coroutine will return the value defined byreturn_value
, hence, by default, the coroutine returns a newCoroutineMock
object.
If the outcome of
side_effect
orreturn_value
is a coroutine, the mock coroutine obtained when the mock object is called will be this coroutine itself (and not a coroutine returning a coroutine).The test author can also specify a wrapped object with
wraps
. In this case, theMock
object behavior is the same as with anunittest.mock.Mock
object: the wrapped object may have methods defined as coroutine functions.-
assert_any_await
(*args, **kwargs)[source]¶ Assert the mock has ever been awaited with the specified arguments.
New in version 0.12.
-
assert_awaited_once
(*args, **kwargs)[source]¶ Assert that the mock was awaited exactly once.
New in version 0.12.
-
assert_awaited_once_with
(*args, **kwargs)[source]¶ Assert that the mock was awaited exactly once and with the specified arguments.
New in version 0.12.
-
assert_awaited_with
(*args, **kwargs)[source]¶ Assert that the last await was with the specified arguments.
New in version 0.12.
-
assert_has_awaits
(calls, any_order=False)[source]¶ Assert the mock has been awaited with the specified calls. The
await_args_list
list is checked for the awaits.If any_order is False (the default) then the awaits must be sequential. There can be extra calls before or after the specified awaits.
If any_order is True then the awaits can be in any order, but they must all appear in
await_args_list
.New in version 0.12.
-
await_args
¶
-
await_args_list
¶
-
await_count
¶ Number of times the mock has been awaited.
New in version 0.12.
-
awaited
¶ Property which is set when the mock is awaited. Its
wait
andwait_next
coroutine methods can be used to synchronize execution.New in version 0.12.
- if
Patch¶
-
asynctest.
GLOBAL
= <PatchScope.GLOBAL: 2>¶ An enumeration.
-
asynctest.
LIMITED
= <PatchScope.LIMITED: 1>¶ An enumeration.
-
asynctest.
patch
(target, new=sentinel.DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, scope=<PatchScope.GLOBAL: 2>, **kwargs)[source]¶ A context manager, function decorator or class decorator which patches the target with the value given by the
new
argument.new
specifies which object will replace thetarget
when the patch is applied. By default, the target will be patched with an instance ofCoroutineMock
if it is a coroutine, or aMagicMock
object.It is a replacement to
unittest.mock.patch()
, but usingasynctest.mock
objects.When a generator or a coroutine is patched using the decorator, the patch is activated or deactivated according to the
scope
argument value:asynctest.GLOBAL
: the default, enables the patch until the generator or the coroutine finishes (returns or raises an exception),asynctest.LIMITED
: the patch will be activated when the generator or coroutine is being executed, and deactivated when it yields a value and pauses its execution (withyield
,yield from
orawait
).
The behavior differs from
unittest.mock.patch()
for generators.When used as a context manager, the patch is still active even if the generator or coroutine is paused, which may affect concurrent tasks:
@asyncio.coroutine def coro(): with asynctest.mock.patch("module.function"): yield from asyncio.get_event_loop().sleep(1) @asyncio.coroutine def independent_coro(): assert not isinstance(module.function, asynctest.mock.Mock) asyncio.create_task(coro()) asyncio.create_task(independent_coro()) # this will raise an AssertionError(coro() is scheduled first)! loop.run_forever()
Parameters: scope – asynctest.GLOBAL
orasynctest.LIMITED
, controls when the patch is activated on generators and coroutinesWhen used as a decorator with a generator based coroutine, the order of the decorators matters. The order of the
@patch()
decorators is in the reverse order of the parameters produced by these patches for the patched function. And the@asyncio.coroutine
decorator should be the last since@patch()
conceptually patches the coroutine, not the function:@patch("module.function2") @patch("module.function1") @asyncio.coroutine def test_coro(self, mock_function1, mock_function2): yield from asyncio.get_event_loop().sleep(1)
New in version 0.6: patch into generators and coroutines with a decorator.
-
asynctest.patch.
object
(target, attribute, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, scope=asynctest.GLOBAL, **kwargs)¶ Patch the named member (
attribute
) on an object (target
) with a mock object, in the same fashion aspatch()
.See
patch()
andunittest.mock.patch.object()
.
-
asynctest.patch.
multiple
(target, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, scope=asynctest.global, **kwargs)¶ Perform multiple patches in a single call. It takes the object to be patched (either as an object or a string to fetch the object by importing) and keyword arguments for the patches.
See
patch()
andunittest.mock.patch.multiple()
.
-
asynctest.patch.
dict
(in_dict, values=(), clear=False, scope=asynctest.GLOBAL, **kwargs)¶ Patch a dictionary, or dictionary like object, and restore the dictionary to its original state after the test.
Its behavior can be controlled on decorated generators and coroutines with
scope
.New in version 0.8: patch into generators and coroutines with a decorator.
Parameters: - in_dict – dictionary like object, or string referencing the object to patch.
- values – a dictionary of values or an iterable of (key, value) pairs to set in the dictionary.
- clear – if
True
, in_dict will be cleared before the new values are set. - scope –
asynctest.GLOBAL
orasynctest.LIMITED
, controls when the patch is activated on generators and coroutines
See: patch()
(details aboutscope
) andunittest.mock.patch.dict()
.
Helpers¶
-
asynctest.
mock_open
(mock=None, read_data='')[source]¶ A helper function to create a mock to replace the use of
open()
. It works foropen()
called directly or used as a context manager.Parameters: - mock – mock object to configure, by default
a
MagicMock
object is created with the API limited to methods or attributes available on standard file handles. - read_data – string for the
read()
andreadlines()
of the file handle to return. This is an empty string by default.
- mock – mock object to configure, by default
a
-
asynctest.
return_once
(value, then=None)[source]¶ Helper to use with
side_effect
, so a mock will return a given value only once, then return another value.When used as a
side_effect
value, if one ofvalue
orthen
is anException
type, an instance of this exception will be raised.>>> mock.recv = Mock(side_effect=return_once(b"data")) >>> mock.recv() b"data" >>> repr(mock.recv()) 'None' >>> repr(mock.recv()) 'None'
>>> mock.recv = Mock(side_effect=return_once(b"data", then=BlockingIOError)) >>> mock.recv() b"data" >>> mock.recv() Traceback BlockingIOError
Parameters: - value – value to be returned once by the mock when called.
- then – value returned for any subsequent call.
New in version 0.4.
Mocking of Selector¶
Mock of selectors
and compatible objects performing asynchronous IO.
This module provides classes to mock objects performing IO (files, sockets,
etc). These mocks are compatible with TestSelector
, which
can simulate the behavior of a selector on the mock objects, or forward actual
work to a real selector.
Mocking file-like objects¶
-
class
asynctest.
FileMock
(*args, **kwargs)[source]¶ Mock a file-like object.
A FileMock is an intelligent mock which can work with TestSelector to simulate IO events during tests.
-
fileno
()¶ Return a
FileDescriptor
object.
-
-
class
asynctest.
SocketMock
(side_effect=None, return_value=sentinel.DEFAULT, wraps=None, name=None, spec_set=None, parent=None, **kwargs)[source]¶ Bases:
asynctest.selector.FileMock
Mock a socket.
See
FileMock
.
-
class
asynctest.
SSLSocketMock
(side_effect=None, return_value=sentinel.DEFAULT, wraps=None, name=None, spec_set=None, parent=None, **kwargs)[source]¶ Bases:
asynctest.selector.SocketMock
Mock a socket wrapped by the
ssl
module.See
FileMock
.New in version 0.5.
-
class
asynctest.
FileDescriptor
[source]¶ Bases:
int
A subclass of int which allows to identify the virtual file-descriptor of a
FileMock
.If
FileDescriptor()
without argument, its value will be the value ofnext_fd
.When an object is created,
next_fd
is set to the highest value for aFileDescriptor
object + 1.-
next_fd
= 0¶
-
Helpers¶
-
asynctest.
fd
(fileobj)[source]¶ Return the
FileDescriptor
value offileobj
.If
fileobj
is aFileDescriptor
,fileobj
is returned, elsefileobj.fileno()
is returned instead.Note that if fileobj is an int,
ValueError
is raised.Raises: ValueError – if fileobj
is not aFileMock
, a file-like object or aFileDescriptor
.
-
asynctest.
isfilemock
(obj)[source]¶ Return
True
if theobj
orobj.fileno()
is aasynctest.FileDescriptor
.
Mocking the selector¶
-
class
asynctest.
TestSelector
(selector=None)[source]¶ A selector which supports IOMock objects.
It can wrap an actual implementation of a selector, so the selector will work both with mocks and real file-like objects.
A common use case is to patch the selector loop:
loop._selector = asynctest.TestSelector(loop._selector)
Parameters: selector – optional, if provided, this selector will be used to work with real file-like objects. -
modify
(fileobj, events, data=None)[source]¶ Shortcut when calling
TestSelector.unregister()
thenTestSelector.register()
to update the registration of a an object to the selector.
-
register
(fileobj, events, data=None)[source]¶ Register a file object or a
FileMock
.If a real selector object has been supplied to the
TestSelector
object andfileobj
is not aFileMock
or aFileDescriptor
returned byFileMock.fileno()
, the object will be registered to the real selector.
-
select
(timeout=None)[source]¶ Perform the selection.
This method is a no-op if no actual selector has been supplied.
-
Helpers¶
-
asynctest.
set_read_ready
(fileobj, loop)[source]¶ Schedule callbacks registered on
loop
as if the selector notified that data is ready to be read onfileobj
.Parameters: - fileobj – file object or
FileMock
on which the event is mocked. - loop –
asyncio.SelectorEventLoop
watching for events onfileobj
.
mock = asynctest.SocketMock() mock.recv.return_value = b"Data" def read_ready(sock): print("received:", sock.recv(1024)) loop.add_reader(mock, read_ready, mock) set_read_ready() loop.run_forever() # prints received: b"Data"
New in version 0.4.
- fileobj – file object or
-
asynctest.
set_write_ready
(fileobj, loop)[source]¶ Schedule callbacks registered on
loop
as if the selector notified that data can be written tofileobj
.Parameters: - fileobj – file object or
FileMock
on which th event is mocked. - loop –
asyncio.SelectorEventLoop
watching for events onfileobj
.
New in version 0.4.
- fileobj – file object or
Contribute¶
Development of asynctest
is on github:
Martiusweb/asynctest.
Patches, feature requests and bug reports are welcome.