從pytest源碼的角度分析pytest工作原理
2024-07-30 16:00 清風軟件測試開發 閱讀(807) 評論(0) 收藏 舉報從pytest源碼的角度分析pytest工作原理
從 pytest 源代碼的角度來分析其工作原理,我們需要關注幾個關鍵的部分,特別是 pytest 的啟動過程以及測試的收集與執行。下面是基于 pytest 源代碼的一個高層次的概述。

pytest 的啟動過程
-
命令行解析:
pytest的入口點是conftest.py文件中的pytest.main()函數。- 在這個函數中,首先通過
pytest.config.get_config()獲取配置。 - 接著使用
pytest.config.parse()來解析命令行參數。
-
配置加載:
pytest會在當前目錄及其父目錄遞歸地查找配置文件,比如pytest.ini或pyproject.toml。- 使用
pytest.config.Config類來存儲配置信息。
-
插件管理:
- 通過
pytest.hookspec和pytest.pluginmanager來管理插件。 - 插件可以在各個階段被注冊并調用。
- 通過
測試收集過程
-
收集器初始化:
pytest使用pytest.collect模塊來處理測試收集。Session.from_parent方法創建一個新的Session實例。Collector.from_parent方法用于構建收集器樹。
-
測試文件發現:
pytest通過Session.perform_collect方法來遍歷目錄結構并發現測試模塊。File.from_parent方法用于創建File實例來代表測試文件。Function.from_parent方法用于創建Function實例來代表測試函數。
-
測試項構建:
- 一旦發現了測試文件,就會通過
collect方法來收集文件中的測試函數。 - 測試函數會被轉換成
Item實例。
- 一旦發現了測試文件,就會通過
測試執行過程
-
測試項準備:
- 在測試開始之前,會調用
Session.perform_setup方法來進行一些預處理。 - 這個階段可能包括設置環境變量、初始化數據庫連接等。
- 在測試開始之前,會調用
-
測試項執行:
Session.runtestloop方法控制測試項的實際執行。- 對于每一個
Item實例,都會調用Session.perform_test方法來執行測試。
-
測試結果收集:
- 測試執行的結果會被收集并存儲在
Item實例中。 - 可能會觸發
pytest_runtest_logreporthook,該 hook 被用來處理測試報告。
- 測試執行的結果會被收集并存儲在
-
異常處理:
- 如果測試過程中發生異常,
pytest會捕獲這些異常并記錄下來。 - 異常可以通過
pytest_runtest_makereporthook 來處理。
- 如果測試過程中發生異常,
測試報告生成
Session實例負責收集所有的測試結果。Session.exitstatus屬性會根據測試結果來確定程序的退出狀態碼。pytest可以生成多種格式的報告,這取決于安裝的插件。
示例代碼片段
下面是一些示例代碼片段,展示了 pytest 源代碼中的關鍵部分:
# pytest/conftest.py def main(args=None): # 解析命令行參數 config = get_config(args) # 加載插件 pm = PluginManager() pm.load_setuptools_entrypoints('pytest11') # 創建 Session 實例 session = Session.from_parent(config, plugins=pm) # 執行測試 session.runtestloop() # 返回退出狀態 return session.exitstatus # pytest/collect.py def perform_collect(session, collector): # 收集測試文件和測試函數 items = [] for item in collector.collect(): items.append(item) return items # pytest/runner.py def runtest_protocol(item, nextitem): # 執行測試項 report = item.runtest() if report is None: # 處理異常情況 report = item.makereport() # 處理測試報告 item.session._hookmanager.hook.pytest_runtest_logreport(report=report)
浙公網安備 33010602011771號