kri*_*nab 8 python testing fixtures pytest
我正在用来pytest
为我正在开发的包运行测试用例。这些测试使用我已保存为 github 资源的小图像文件。下面的代码工作得很好,但我认为pytest
每次运行新测试时都会下载图像,这会花费不必要的时间和资源。我试图弄清楚如何下载一次文件,然后在测试用例之间共享它
这是一些示例代码。
# -- in conftest.py --
import sys
import pytest
import os
import shutil
import requests
@pytest.fixture(scope="function")
def small_image(tmpdir):
url = 'https://github.com/.../sample_image_small.tif'
r = requests.get(url)
with open(os.path.join(str(tmpdir), 'sample_image_small.tif'), 'wb') as f:
f.write(r.content)
return os.path.join(str(tmpdir), 'sample_image_small.tif')
Run Code Online (Sandbox Code Playgroud)
然后这里有一些非常简单的测试用例,应该能够共享相同的图像。
# -- test_package.py --
import pytest
import os
@pytest.mark.usefixtures('small_image')
def test_ispath(small_image, compression):
assert os.path.exists(small_image)
def test_isfile(small_image, compression):
assert os.path.isfile(small_image)
Run Code Online (Sandbox Code Playgroud)
现在我相信pytest
会尝试单独隔离每个测试,这就是导致文件重复下载的原因。我尝试设置@pytest.fixture(scope="module")
代替,function
但这会产生奇怪的错误:
ScopeMismatch: You tried to access the 'function' scoped fixture 'tmpdir' with a 'module' scoped request object, involved factories
Run Code Online (Sandbox Code Playgroud)
有没有更好的方法来设置测试,这样我就不会一遍又一遍地下载文件?
首先,预先说明:旧的tmpdir
/tmpdir_factory
固定装置对的更好替代方案是tmp_path
/ tmp_path_factory
,它处理pathlib
对象而不是已弃用的py.path
,请参阅临时目录和文件。
其次,如果您想处理会话范围(或模块范围)的文件,则tmp*_factory
需要使用固定装置。例子:
@pytest.fixture(scope='session')
def small_image(tmp_path_factory):
img = tmp_path_factory.getbasetemp() / 'sample_image_small.tif'
img.write_bytes(b'spam')
return img
Run Code Online (Sandbox Code Playgroud)
现在每次测试运行都会sample_image_small.tif
写入一次。
当然,按照 @MrBean Bremen 在他的回答中建议的使用没有任何问题tempfile
,这只是做同样的事情的另一种选择,但仅使用标准pytest
装置。
您可以使用相同的代码,只需自己处理临时文件,而不是使用固定tmpdir
装置(不能在模块范围的固定装置中使用):
import os
import tempfile
import pytest
import requests
@pytest.fixture(scope="module")
def small_image():
url = 'https://github.com/.../sample_image_small.tif'
r = requests.get(url)
f = tempfile.NamedTemporaryFile(delete=False):
f.write(f.content)
yield f.name
os.remove(f.name)
Run Code Online (Sandbox Code Playgroud)
这将创建文件,返回文件名,并在测试完成后删除文件。
编辑: @hoefling 的答案显示了一种更标准的方法来做到这一点,我将留下这个供参考。
归档时间: |
|
查看次数: |
2825 次 |
最近记录: |