[英]Python: Assert mock function was called with a string containing another string
這是我面臨的問題的簡化版本:假設我有一個 function 接受目錄路徑,然后刪除其所有內容,除了(可選)指定的“保留文件”,
import os
KEEP_FILE_CONSTANT = '.gitkeep'
def clear_directory(directory: str, retain: bool = True) -> bool:
try:
filelist = list(os.listdir(directory))
for f in filelist:
filename = os.path.basename(f)
if retain and filename == KEEP_FILE_CONSTANT:
continue
os.remove(os.path.join(directory, f))
return True
except OSError as e:
print(e)
return False
我正在嘗試為此 function 編寫一個單元測試,以驗證調用了os.remove
。 這是目前我正在測試它的方式:
import pytest
from unittest.mock import ANY
@pytest.mark.parametrize('directory', [
('random_directory_1'),
('random_directory_2'),
# ...
])
@patch('module.os.remove')
def test_clear_directory(delete_function, directory):
clear_directory(directory)
delete_function.assert_called()
delete_function.assert_called_with(ANY)
理想情況下,我想在測試中斷言的是delete_function
是使用包含directory
的參數調用的,例如,
delete_function.assert_called_with(CONTAINS(directory))
或類似的東西。 我一直在查看PyHamcrest ,特別是contains_string function,但我不確定如何在此處應用它,或者是否可能。
有沒有辦法為這個用例實現一個 CONTAINS 匹配器?
這不是您問題的直接答案,但如果我正在編寫這些測試,我會采取不同的方法:
這樣,您正在測試您想要的實際行為,而不是依賴於內部實現細節(即您使用os.remove()
而不是Pathlib.unlink()
() 之類的替代方法)。
如果您不熟悉,pytest 為此類測試提供了一個tmp_path
夾具。 但是,填充臨時目錄仍然有點麻煩,尤其是如果您想測試各種嵌套文件層次結構。 不過,我編寫了一個名為tmp_files
的夾具來簡化此操作,我認為它可能非常適合您的問題。 以下是測試的外觀:
import pytest
# I included tests for nested files, even though the sample function you
# provided doesn't support them, just to show how to do it.
@pytest.mark.parametrize(
'tmp_files, to_remove, to_keep', [
pytest.param(
{'file.txt': ''},
['file.txt'],
[],
id='remove-1-file',
),
pytest.param(
{'file-1.txt': '', 'file-2.txt': ''},
['file-1.txt', 'file-2.txt'],
[],
id='remove-2-files',
),
pytest.param(
{'file.txt': '', 'dir/file.txt': ''},
['file.txt', 'dir/file.txt'],
[],
id='remove-nested-files',
marks=pytest.mark.xfail,
),
pytest.param(
{'.gitkeep': ''},
[],
['.gitkeep'],
id='keep-1-file',
),
pytest.param(
{'.gitkeep': '', 'dir/.gitkeep': ''},
[],
['.gitkeep', 'dir/.gitkeep'],
id='keep-nested-files',
marks=pytest.mark.xfail,
),
],
indirect=['tmp_files'],
)
def test_clear_directory(tmp_files, to_remove, to_keep):
clear_directory(tmp_files)
for p in to_remove:
assert not os.path.exists(tmp_files / p)
for p in to_keep:
assert os.path.exists(tmp_files / p)
簡單解釋一下, tmp_files
參數指定要在每個臨時目錄中創建哪些文件,並且只是將文件名映射到文件內容的字典。 這里所有的文件都是簡單的文本文件,但也可以創建符號鏈接、FIFO 等indirect=['tmp_files']
參數很容易忽略但非常重要。 它告訴 pytest 使用tmp_files
參數對tmp_files
夾具進行參數化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.