Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Neil Chazin - Strategies for testing Async code

Neil Chazin - Strategies for testing Async code

Testing code is important. Testing, primarily unit-testing async code requires heading off the the standard roadway of unit testing in python. This talk will provide a map to help you along the new path towards testing async code.

Topics include:

a brief intro to asyncio and challengs in testing with it
running coroutines (and other awaitables) under test
mocking coroutines
testing "main" asyncio loops

https://us.pycon.org/2019/schedule/presentation/215/

PyCon 2019

May 05, 2019
Tweet

More Decks by PyCon 2019

Other Decks in Programming

Transcript

  1. Strategies For Testing Async Code
    Neil Chazin

    View Slide

  2. Who am I?
    — Programming in Python since the early 2000s
    — Believe that testing software is important
    — @neilathotep
    neil chazin - @neilathotep

    View Slide

  3. Work
    — Currently Senior Software
    Engineer/Tech Lead at Agari
    — Agari secures digital
    communications to ensure
    humanity prevails over evil
    neil chazin - @neilathotep

    View Slide

  4. Brief Outline
    1. Why?
    2. Quick intro to async & asyncio
    3. Challenges of testing
    — Some solutions I've found
    4. Wrap up
    neil chazin - @neilathotep

    View Slide

  5. Why?
    neil chazin - @neilathotep

    View Slide

  6. — Testing is important
    — Performance is often important
    neil chazin - @neilathotep

    View Slide

  7. neil chazin - @neilathotep

    View Slide

  8. Async in Python
    A very brief intro
    neil chazin - @neilathotep

    View Slide

  9. General Async Basics
    — Concurrency through cooperation
    — yield control when 'waiting' - asynchronous results
    neil chazin - @neilathotep

    View Slide

  10. asyncio
    — framework for asynchronous computing
    — available in stdlib as of 3.4
    — Improved syntax in 3.5
    — Incremental changes in 3.6 and 3.7
    neil chazin - @neilathotep

    View Slide

  11. Two primary concepts
    — Coroutines: perform asynchronous work
    — Event loops: schedule asynchronous work
    neil chazin - @neilathotep

    View Slide

  12. Key syntax
    — async - define a coroutine
    — await - 'call' a coroutine
    neil chazin - @neilathotep

    View Slide

  13. Example use case
    We need something simple...
    neil chazin - @neilathotep

    View Slide

  14. neil chazin - @neilathotep

    View Slide

  15. neil chazin - @neilathotep

    View Slide

  16. neil chazin - @neilathotep

    View Slide

  17. neil chazin - @neilathotep

    View Slide

  18. neil chazin - @neilathotep

    View Slide

  19. Challenge
    Testing a coroutine
    neil chazin - @neilathotep

    View Slide

  20. Call as a function
    neil chazin - @neilathotep

    View Slide

  21. Call as a function
    neil chazin - @neilathotep

    View Slide

  22. Tests pass but...
    neil chazin - @neilathotep

    View Slide

  23. Tests pass but...
    neil chazin - @neilathotep

    View Slide

  24. Await the coroutine
    neil chazin - @neilathotep

    View Slide

  25. SyntaxError
    neil chazin - @neilathotep

    View Slide

  26. Run in an event loop
    neil chazin - @neilathotep

    View Slide

  27. Run in an event loop
    neil chazin - @neilathotep

    View Slide

  28. Success
    neil chazin - @neilathotep

    View Slide

  29. Use pytest-asyncio
    — pip install pytest-asyncio
    neil chazin - @neilathotep

    View Slide

  30. neil chazin - @neilathotep

    View Slide

  31. neil chazin - @neilathotep

    View Slide

  32. neil chazin - @neilathotep

    View Slide

  33. neil chazin - @neilathotep

    View Slide

  34. Python 3.7
    New function asyncio.run() simplifies things
    neil chazin - @neilathotep

    View Slide

  35. neil chazin - @neilathotep

    View Slide

  36. Challenge
    Mocks and patching
    neil chazin - @neilathotep

    View Slide

  37. Mocks o!en relied upon
    — Unittest.mock.Mock won't mock a coroutine
    neil chazin - @neilathotep

    View Slide

  38. neil chazin - @neilathotep

    View Slide

  39. neil chazin - @neilathotep

    View Slide

  40. neil chazin - @neilathotep

    View Slide

  41. neil chazin - @neilathotep

    View Slide

  42. neil chazin - @neilathotep

    View Slide

  43. Challenge
    Context managers
    neil chazin - @neilathotep

    View Slide

  44. neil chazin - @neilathotep

    View Slide

  45. Challenge
    More complex use cases
    neil chazin - @neilathotep

    View Slide

  46. — Previous patterns all work great but some short
    comings I've found:
    — test coroutines that do not run in the MainThread
    when executing
    — test syncronous functions that call into event
    loops ()
    — functional tests
    — Event Loop variants (e.g. uvloop)
    neil chazin - @neilathotep

    View Slide

  47. neil chazin - @neilathotep

    View Slide

  48. neil chazin - @neilathotep

    View Slide

  49. neil chazin - @neilathotep

    View Slide

  50. neil chazin - @neilathotep

    View Slide

  51. Calling across threads
    neil chazin - @neilathotep

    View Slide

  52. neil chazin - @neilathotep

    View Slide

  53. neil chazin - @neilathotep

    View Slide

  54. neil chazin - @neilathotep

    View Slide

  55. neil chazin - @neilathotep

    View Slide

  56. neil chazin - @neilathotep

    View Slide

  57. neil chazin - @neilathotep

    View Slide

  58. Wrap up
    — Try out asyncio programming
    — Keep testing
    — Find sample code and presentation at:
    h!ps://bit.ly/nchazin-pycon2019
    neil chazin - @neilathotep

    View Slide