鉤子 【pytest官方文檔】解讀-插件開發之hooks 函數

上一節講到如何安裝和使用第三方插件,用法很簡單 。接下來解讀下如何自己開發pytest插件 。
但是,由于一個插件包含一個或多個鉤子函數開發而來 , 所以在具體開發插件之前還需要先學習hooks函數 。
一、什么是 hooks 函數簡單來說,在 pytest 的代碼中,預留出了一些函數供我們修改,以便來改變pytest工作方式 , 這些函數就是hooks函數,我們可以直接重寫函數里的內容 。
比如,在 pytest代碼路徑\Lib\site-packages\_pytest\hookspec.py中,可以看到 pytest 定義好的 hook 規范,方便我們在開發插件的時候參考規范來調用對應的hooks函數 。

鉤子 【pytest官方文檔】解讀-插件開發之hooks 函數

文章插圖
二、hooks 函數的分類從hooks函數的職責分類來看,大概如下幾類:
  • Bootstrapping hooks:引導類鉤子,用來調用已經早就注冊好的內部插件和第三方插件 。
  • Collection hooks:集合類鉤子 , pytest 調用集合鉤子來收集文件和目錄 。
  • Test running (runtest) hooks:測試運行相關的鉤子,所有與測試運行相關的鉤子都接收一個pytest.Item對象 。
  • Reporting hooks:與Session 會話相關的鉤子 。
  • Debugging/Interaction hooks:調試/交互鉤子,少有的可以用于特殊的報告或與異常交互的鉤子函數 。
可供調用的鉤子函數有很多,功能也是各式各樣的,有興趣的童鞋可以進一步細看官方文檔里的介紹 。我們就是要通過不同鉤子函數具備的功能 , 來實現我們自定義的需求 。
三、編寫 hooks 函數開發本地插件寫一個插件示例 。
比如我們平時執行case的時候 , 一通跑完可能會出現不少失敗的case,那通常我可能就會翻控制臺的輸出來找出哪些case失敗了 。
但是控制臺里輸出的信息有很多,于是乎我想直接把測試失敗的case信息存到一個本地文件里 , 我直接打開就可以看到所有失敗的case 。
先寫一個case文件里的建議測試用例:
# content of mytest/tests.pydef test_failed():assert Falsedef test_passed():assert Truedef test_failed2():assert False然后再同級目錄下創建一個conftest文件,之前聊fixture時候就說過,conftest里的內容就是本地插件了 。
先直接放上插件代碼:
# content of mytest/conftest.pyimport pytestfrom pathlib import Pathfrom _pytest.main import Sessionfrom _pytest.nodes import Itemfrom _pytest.runner import CallInfofrom _pytest.terminal import TerminalReporterFAILURES_FILE = Path() / "failures.txt"@pytest.hookimpl()def pytest_sessionstart(session: Session):print("Hello 把蘋果咬哭")if FAILURES_FILE.exists():FAILURES_FILE.unlink()FAILURES_FILE.touch()@pytest.hookimpl(hookwrapper=True)def pytest_runtest_makereport(item: Item, call: CallInfo):outcome = yieldresult = outcome.get_result()if result.when == "call" and result.failed:try:with open(str(FAILURES_FILE), "a") as f:f.write(result.nodeid + "\n")except Exception as e:print("ERROR", e)pass解析
1. 重寫鉤子函數首先,關于pathlib模塊就是用來做一些路徑操作的庫,因為我要在本地路徑中進行文件相關操作 。
def pytest_sessionstart()中做的事情就是先看下本地是否存在這個名字叫failures.txt的文件 , 有的話就刪除,沒有就新建 。
為啥用pytest_sessionstart這個hook函數,因為通過查看官方API文檔里的介紹 , 發現這個鉤子函數是在創建Session對象之后,且在執行收集和進入運行測試循環之前調用,所以很適合用在這里 。
所以直接重寫這個hook函數來實現我們定義的功能 。
2. hook函數中的 firstresult示例中使用hook函數pytest_runtest_makereport,同樣通過查看官方API介紹 , 它的作用是為測試用例的每個setup運行tearDown階段創建TestReport 。而插件要做的事情,就是要在用例執行后獲取到狀態,若是失敗就存放到本地txt文件 。
當查看hook規范時候 , 發現一個裝飾器參數firstresult=True 。
鉤子 【pytest官方文檔】解讀-插件開發之hooks 函數

文章插圖
由于在大多數情況下,調用hook函數可能還會觸發調用多個hook,所以最后的結果會是包含所調用鉤子函數的非none結果
firstresult=True時,調用鉤子函數時只要有第一個返回非none結果,就會將該結果作為整個鉤子調用的結果 。在這種情況下,將不會調用其余鉤子函數 。

推薦閱讀