摘要:整個事件循環是在一個線程里面的,意味著任務切換更加高效,無需上下文轉換。異步代碼很高效,但是也有很蛋疼的地方,那就是測試。所以我們得想辦法告訴使用一個來運行測試方法。
視頻原文:Strategies for testing Async code - PyCon 2019
同時參考了:
Testing Asyncio Python Code with Pytest
前面幾篇關于異步編程的文章:
異步編程 101: 是什么、小試Python asyncio
異步編程 101:Python async await發展簡史
異步編程 101:寫一個事件循環
異步編程 101:asyncio中的 for 循環
異步編程 101:asyncio 進階上篇
異步編程,本質上是通過合作(cooperation)來達成并發效果,也即:需要 wait 的時候,也就是發生 IO 的時候,把控制權交給主事件循環。 (yield control when "awaiting" asynchronous results.) 這個過程有點像事件循環完成了操作系統的工作,可以將事件循環看作是操作系統,然后把協程看作是線程這么來理解。整個事件循環是在一個線程里面的,意味著任務切換更加高效,無需上下文轉換。
異步代碼很高效,但是也有很蛋疼的地方,那就是測試。
0x01 : async 測試實例來通過一個簡單的例子看一下吧:一個Cat類,有一個 move 方法,這個方法是異步的。
然后用 unittest 寫一個測試類,你能發現下面代碼的問題嗎?
herd(grafield, "forward") 返回的是一個協程對象(coroutine object),如果你不await他,什么也不會發生。而coroutine object是 truthy 的,所以assertTrue() 是能夠通過的。如果你運行一下 test,會看到coroutine herd was nerver awaited的 warning。
下圖這樣調用await還是不對的,因為await關鍵字只能出現在async函數里面。
一個解決方案是加入事件循環:
這能work,但是估計你也看出來了,這很麻煩。如果我有多個方法,難道我需要每個 test方法都加一個事件循環嗎?更重要的是,我只是想做一下單元測試,事件循環在這個時候實際上是一個底層細節,我不需要關心。
在 Python3.7 中,asyncio新增了一個方法:asyncio.run(),為你隱藏了事件循環的細節,所以能夠讓代碼更加簡潔:
0x02 pytest-asyncio
安裝:pip install pytest-asyncio,這實際上是pytest的一個插件。
用法很簡單,重要的是我們得知道工作原理。之前的代碼問題在于,pytest 默認的的 runner 會將所有的函數當作普通函數處理,而對于 async 函數, 調用的時候返回的是一個 coroutine object。所以我們得想辦法告訴 pytest 使用一個 eventloop 來運行測試方法。
一種方法是,實例化一個eventloop 然后注入到 tests里面,比如:
import asyncio
import pytest
async def say(what, when):
await asyncio.sleep(when)
return what
@pytest.fixture
def event_loop():
loop = asyncio.get_event_loop()
yield loop
loop.close()
def test_say(event_loop):
expected = "This should fail!"
assert expected == event_loop.run_until_complete(say("Hello!", 0))
這種方法不方便之處在于每次都需要手動注入 eventloop,更優雅的方法是調整 test runner,讓它識別 async 函數,當作 asyncio tasks 來執行。
pytest-asyncio完成的功能就是這樣的,它的 API 非常簡單,你只需要為 async function 添加一個 @pytest.mark.asyncio 修飾器即可:
import pytest
from say import say
@pytest.mark.asyncio
async def test_say():
assert "Hello!" == await say("Hello!", 0)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/7001.html
摘要:蜂鳥網圖片簡介今天玩點新鮮的,使用一個新庫,利用它提高咱爬蟲的爬取速度。上下文不在提示,自行搜索相關資料即可創建一個對象,然后用該對象去打開網頁。可以進行多項操作,比如等代碼中等待網頁數據返回創建線程,方法負責安排執行中的任務。 1. 蜂鳥網圖片-簡介 今天玩點新鮮的,使用一個新庫 aiohttp ,利用它提高咱爬蟲的爬取速度。 安裝模塊常規套路 pip install aiohtt...
摘要:蜂鳥網圖片簡介今天玩點新鮮的,使用一個新庫,利用它提高咱爬蟲的爬取速度。上下文不在提示,自行搜索相關資料即可創建一個對象,然后用該對象去打開網頁。可以進行多項操作,比如等代碼中等待網頁數據返回創建線程,方法負責安排執行中的任務。 1. 蜂鳥網圖片-簡介 今天玩點新鮮的,使用一個新庫 aiohttp ,利用它提高咱爬蟲的爬取速度。 安裝模塊常規套路 pip install aiohtt...
摘要:蜂鳥網圖片簡介今天玩點新鮮的,使用一個新庫,利用它提高咱爬蟲的爬取速度。上下文不在提示,自行搜索相關資料即可創建一個對象,然后用該對象去打開網頁。可以進行多項操作,比如等代碼中等待網頁數據返回創建線程,方法負責安排執行中的任務。 1. 蜂鳥網圖片-簡介 今天玩點新鮮的,使用一個新庫 aiohttp ,利用它提高咱爬蟲的爬取速度。 安裝模塊常規套路 pip install aiohtt...
摘要:發現一個月沒刷技術文章了有點慌整理一篇短的用法出來只包含最基本的用法在里邊最清晰不過我是在寫的版本的實現包含異步用法會更繁瑣一些但是也值得看看我相信普及之前還是一個很有意思的選擇我的代碼寫的是可以自動腦補圓括號花括號上去注意包含的函數自動 發現一個月沒刷技術文章了, 有點慌, 整理一篇短的 CSP 用法出來,只包含最基本的用法, 在 Go 里邊最清晰, 不過我是在 Clojure 寫的...
閱讀 2650·2021-11-23 09:51
閱讀 2422·2021-09-30 09:48
閱讀 2050·2021-09-22 15:24
閱讀 1014·2021-09-06 15:02
閱讀 3312·2021-08-17 10:14
閱讀 1941·2021-07-30 18:50
閱讀 1986·2019-08-30 15:53
閱讀 3182·2019-08-29 18:43