[Python-ideas] async unittest.TestCase

David Shawley daveshawley at gmail.com
Fri Oct 26 08:48:57 EDT 2018

On Oct 10, 2018, at 1:34 PM, Serhiy Storchaka <storchaka at gmail.com> wrote:
> 10.10.18 20:19, Yury Selivanov пише:
> > Thanks for proposing this.  Yes, it makes sense to have
> > unittest.AsyncTestCase in 3.8.  AFAIK Lisa Roach (copied) was working
> > on that (as well as on async Mock object), but I'm not sure what's the
> > status of her work.  I suggest to search for an open issue for this on
> > bugs.python.org; if there's none, please create one.  And let's make
> > this happen.
> https://bugs.python.org/issue32972
> https://bugs.python.org/issue26467

I have a working prototype of asynchronous testing in a branch on github [1]
but I took a different approach than what was discussed in bpo-32972.
I open a new bpo or continue the discussion on the existing bpo?

I'm leaning in the direction of opening a new bpo so as to not muddy the
waters with the discussion around the other branch.

Here's a summary of the approach that I took:

- create a new class unittest.AsyncioTestCase that implements a few
  new methods and attributes:

   - asyncSetUp / asyncTearDown: are awaitable and call the synchronous
     setUp and tearDown methods.  These only exist on the new sub-class.

   - _runTest: a new method on unittest.TestCase that encapsulates running
     the test case. This is simply the portion of unittest.TestCase.run()
     that runs setUp()/testMethod()/tearDown().

   - _terminateTest: a new method on unittest.TestCase that is *always*
     called from within run() immediately *before* calling stopTest() on
     the result.  The AsyncioTestCase specialization of this method is
     responsible to cleaning up the event loop in the same manner that
     asyncio.run() does.  In particular, it shuts down asynchronous
     generators. [a]

   - event_loop: an overridable property on the new sub-class that creates
     and installs a new event loop.  This is referred to from within the
     AsyncioTestCase specialization of _runTest to create the event loop

- event loops are created and destroyed for each test method [b]

- the same event loop persists from before setUp until after the cleanups
  are called

- test methods that asyncio.iscoroutinefunction thinks are co-routines
  are run on the event loop; other test methods are called directly [c]

With that said, should I open a new bpo or start discussion on the existing
one anew?

Cheers, dave.

[1]: https://github.com/dave-shawley/cpython/pull/1
[2]: https://github.com/python/cpython/pull/9296

[a]: I explicitly chose to not shutdown outstanding tasks in _terminateTest
so that the event loop complains loudly about them.  This is an area that I
would like to discuss further.

[b]: I chose to create and destroy an event loop with each test method to
avoid having tasks and other event loop settings from leaking between test

[c]: This is problematic since mock.patch decorated co-routines won't be
called correctly.  I'm going to discuss this with @lisroach on her bpo-26467
patch [2].  I have a feeling that the "AwaitableMock" approach may work out
and change this code.  See the most recent comments on [2] for details.

People think right angles produce harmony, but they don't. They produce
  -- James Krenov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20181026/fddcc3cb/attachment.html>

More information about the Python-ideas mailing list