詳解如何利用Pytest?Cache?Fixture實現(xiàn)測試結(jié)果緩存
前言
接口自動關(guān)過程中,經(jīng)常會遇到這樣一些場景,"請求2需要用到請求1響應(yīng)的數(shù)據(jù)",常見的做法,進行用例依賴或者將請求1的響應(yīng)結(jié)果寫入一個文件,用到的時候讀取文件。當然這都不是這篇文章的重點,本片文章主要介紹cache寫入和讀取緩存數(shù)據(jù)。
request.config.cache
還不了解request fixture的同學可以先看看這篇文章,pytest 的 request fixture:實現(xiàn)個性化測試需求
我們先看看使用案例:
def test_01(cache):
? ?cache.set("token", "uiouoouoiou")
?
def test_02(cache):
? ?r = cache.get("token", None)這樣段代碼在執(zhí)行test_01會將token值緩存,任何執(zhí)行test_02時就可以從緩存中讀取token值。那Cache是如何實現(xiàn)的呢?我們一起來看看源碼。源碼直達
實現(xiàn)原理
def test_01(cache):
? ?cache.set("token", {"token": "1212121"})我們在cache.set()這一行進行斷點,debug執(zhí)行后,debug結(jié)果為
cache = Cache()
_CACHE_PREFIX_DIRS = 'd'
_CACHE_PREFIX_VALUES = 'v'
_cachedir = /PycharmProjects/panda-test/org/.pytest_cache
_config = <_pytest.config.Config object at 0x109e80d60>
可以看到會自動創(chuàng)建一個緩存實例,而且初始化了一些數(shù)據(jù),默認應(yīng)該緩存文件會在.pytest_cache目錄下
/_pytest/cacheprovider.py
@fixture def cache(request: FixtureRequest) -> Cache: ? ?"""Return a cache object that can persist state between testing sessions. ? ? cache.get(key, default) ? cache.set(key, value) ? ? Keys must be ``/`` separated strings, where the first part is usually the ? name of your plugin or application to avoid clashes with other cache users. ? ? Values can be any object handled by the json stdlib module. ? """ ? ?assert request.config.cache is not None ? ?return request.config.cache
可以看到,cache返回的是Cache對象,我們看看Cache對象是如何實現(xiàn)的
? ?def set(self, key: str, value: object) -> None:
? ? ? ?path = self._getvaluepath(key)
? ? ? ?try:
? ? ? ? ? ?if path.parent.is_dir():
? ? ? ? ? ? ? ?cache_dir_exists_already = True
? ? ? ? ? ?else:
? ? ? ? ? ? ? ?cache_dir_exists_already = self._cachedir.exists()
? ? ? ? ? ? ? ?path.parent.mkdir(exist_ok=True, parents=True)
? ? ? ?except OSError:
? ? ? ? ? ?self.warn("could not create cache path {path}", path=path, _ispytest=True)
? ? ? ? ? ?return
? ? ? ?if not cache_dir_exists_already:
? ? ? ? ? ?self._ensure_supporting_files()
? ? ? ?data = json.dumps(value, ensure_ascii=False, indent=2)
? ? ? ?try:
? ? ? ? ? ?f = path.open("w", encoding="UTF-8")
? ? ? ?except OSError:
? ? ? ? ? ?self.warn("cache could not write path {path}", path=path, _ispytest=True)
? ? ? ?else:
? ? ? ? ? ?with f:
? ? ? ? ? ? ? ?f.write(data)這段源碼就是用來將鍵值對保存到緩存中。代碼比較簡單,簡單解釋一下
- 獲取要保存的鍵值對的路徑:通過調(diào)用
_getvaluepath()方法,根據(jù)給定的鍵(key)獲取值(value)在緩存中的路徑(path)。這里的路徑是一個字符串,使用/分隔不同的層級,通常第一個名稱是插件或應(yīng)用程序的名稱。 - 檢查路徑是否存在:通過判斷路徑的父目錄是否為目錄來確定是否需要創(chuàng)建路徑。如果父目錄已經(jīng)存在,則
cache_dir_exists_already設(shè)置為True;否則,它會檢查緩存目錄是否存在,并且如果緩存目錄已經(jīng)存在,則cache_dir_exists_already設(shè)置為True,否則創(chuàng)建緩存目錄。 - 確保支持文件已存在:如果緩存目錄是新創(chuàng)建的,則調(diào)用
_ensure_supporting_files()方法確保支持文件存在。這個方法可能是用來創(chuàng)建其他與緩存相關(guān)的文件或目錄。 - 序列化數(shù)據(jù)并寫入文件:將值(
value)使用 JSON 格式進行序列化,以確保它是基本的 Python 類型或包含了嵌套類型(例如列表和字典)。然后,嘗試打開路徑對應(yīng)的文件(使用 UTF-8 編碼),并將序列化后的數(shù)據(jù)寫入文件中。
? ?def get(self, key: str, default):
? ? ? ?path = self._getvaluepath(key)
? ? ? ?try:
? ? ? ? ? ?with path.open("r", encoding="UTF-8") as f:
? ? ? ? ? ? ? ?return json.load(f)
? ? ? ?except (ValueError, OSError):
? ? ? ? ? ?return default這段源碼用來從緩存中獲取指定鍵的值,簡單解釋一下:
- 獲取要獲取值的路徑:通過調(diào)用
_getvaluepath()方法,根據(jù)給定的鍵(key)獲取值在緩存中的路徑(path)。這里的路徑是一個字符串,使用/分隔不同的層級,通常第一個名稱是插件或應(yīng)用程序的名稱。 - 嘗試讀取文件并返回已緩存的值:使用路徑對應(yīng)的文件(使用 UTF-8 編碼)打開,并使用
json.load(f)將文件中的數(shù)據(jù)加載為 Python 對象。然后將加載的值返回。 - 處理異常情況:如果無法將文件中的內(nèi)容解析為有效的 JSON 數(shù)據(jù)或者打開文件失敗,則捕獲異常(
ValueError和OSError),并返回默認值(default)。
這里還是學習到了一種新奇的寫法,以前沒用過with path.open("r", encoding="UTF-8") as f:等價于open(path, "r", encoding="UTF-8")
這是兩個常用的方法,當然還提供了更多方法,這里簡單介紹一下:
__init__(self, cachedir: Path, config: Config, *, _ispytest: bool = False) -> None:
初始化方法,用于設(shè)置類的屬性 _cachedir 和 _config。
for_config(cls, config: Config, *, _ispytest: bool = False) -> "Cache":
- 類方法,根據(jù)給定的配置信息創(chuàng)建并返回
Cache實例。 - 如果配置項
cacheclear設(shè)置為True,并且緩存目錄存在,則調(diào)用clear_cache方法清空緩存。 - 最后返回一個新的
Cache實例。
clear_cache(cls, cachedir: Path, _ispytest: bool = False) -> None:
- 類方法,清空緩存目錄下的子目錄。
- 根據(jù)參數(shù)
cachedir構(gòu)建子目錄路徑,并使用rm_rf函數(shù)遞歸刪除該目錄。
cache_dir_from_config(config: Config, *, _ispytest: bool = False) -> Path:
- 靜態(tài)方法,從給定的配置信息中獲取緩存目錄的路徑。
- 首先從配置中獲取緩存目錄的字符串表示,然后使用
resolve_from_str函數(shù)將其解析為Path對象返回。
warn(self, fmt: str, *, _ispytest: bool = False, **args: object) -> None:
- 發(fā)出緩存警告的方法。
- 使用
warnings.warn函數(shù)發(fā)出警告信息,并指定警告類型為PytestCacheWarning。 - 如果存在參數(shù)
args,則將其作為格式化參數(shù)替換格式字符串中的占位符。
mkdir(self, name: str) -> Path:
- 創(chuàng)建一個目錄路徑對象,并在緩存目錄下創(chuàng)建該目錄。
- 參數(shù)
name是要創(chuàng)建的目錄名稱。 - 檢查目錄名是否包含路徑分隔符
/,如果有則拋出異常。 - 使用
_cachedir.joinpath方法構(gòu)建完整的目錄路徑,并使用mkdir方法創(chuàng)建目錄。 - 返回創(chuàng)建的目錄路徑對象。
_getvaluepath(self, key: str) -> Path:
- 根據(jù)給定的鍵生成值文件的路徑。
- 在緩存目錄下構(gòu)建值文件路徑,使用
_CACHE_PREFIX_VALUES作為子目錄前綴。
_ensure_supporting_files(self) -> None:
- 創(chuàng)建緩存目錄中的支持文件。
- 創(chuàng)建
README.md文件,用于說明緩存目錄的用途。 - 創(chuàng)建
.gitignore文件,忽略緩存目錄下的所有文件。 - 創(chuàng)建
CACHEDIR.TAG文件,用于標記緩存目錄。
最后
cache功能還是很實用的,比如登錄功能,可以在登錄之后,將token寫入緩存,這樣進行其他接口請求時,需要token時直接從緩存獲取token即可。
到此這篇關(guān)于詳解如何利用Pytest Cache Fixture實現(xiàn)測試結(jié)果緩存的文章就介紹到這了,更多相關(guān)Pytest Cache Fixture內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
PyTorch?Tensor創(chuàng)建實現(xiàn)
本文主要介紹了PyTorch?Tensor創(chuàng)建實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-06-06
使用Python中的greenlet包實現(xiàn)并發(fā)編程的入門教程
這篇文章主要介紹了使用Python中的greenlet包實現(xiàn)并發(fā)編程的入門教程,Python由于GIL的存在并不能實現(xiàn)真正的多線程并發(fā),greenlet可以做到一個相對的替換方案,需要的朋友可以參考下2015-04-04
Python實現(xiàn)圖片轉(zhuǎn)字符畫的示例
本篇文章主要介紹了Python實現(xiàn)圖片轉(zhuǎn)字符畫的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08

