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() and tearDown() 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 to True, 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 to True, a call to asyncio.get_event_loop() will raise an AssertionError. Since Python 3.6, calling asyncio.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() and tearDown() are coroutine functions, they will run on the loop. Note that setUpClass() and tearDownClass() 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 extensible fail_on() decorator.

setUp()[source]

Method or coroutine called to prepare the test fixture.

see unittest.TestCase.setUp()

tearDown()[source]

Method called immediately after the test method has been called and the result recorded.

see unittest.TestCase.tearDown()

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 awaiting awaitable, a future or coroutine.

See:unittest.TestCase.assertRaises()
assertAsyncRaisesRegex(exception, regex, awaitable)[source]

Like assertAsyncRaises() but also tests that regex 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 that regex matches on the message of the triggered warning.

See:unittest.TestCase.assertWarnsRegex()
doCleanups()[source]

Execute all cleanup functions. Normally called for you after tearDown.

forbid_get_event_loop = False

If true, the value returned by asyncio.get_event_loop() will be set to None 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 for FunctionTestCase.

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 at t + 1. Hence, it will run at t = 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 (with add_reader() or add_writer()) is later explicitly unregistered (with remove_reader() or remove_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 helper exhaust_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 from unittest.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 to True.

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 to False.

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 by ignore_loop().

Deprecated since version 0.8: Use fail_on() with unused_loop=False instead.