使用pytest夹具下载一次数据,但在每次测试中使用新的副本

3 人关注

我有测试代码,下载一组图片,对它们进行一些处理,并断言处理工作符合预期。

@pytest.fixture
def image_dir(tmp_path):
    test_imgs = [
        # ... list of img URLs
    for idx, im_url in enumerate(test_imgs):
        urllib.request.urlretrieve(im_url, tmp_path / f"{idx}.png")
    yield tmp_path
def test_op_A(image_dir: Path):
    for im_path in image_dir.iterdir():
        # load the image
        # modify the image
        # save the image back to disk
    # assert that the modification worked as expected
def test_op_B(image_dir: Path):
    for im_path in image_dir.iterdir():
        # load the image
        # modify the image
        # save the image back to disk
    # assert that the modification worked as expected
# ... more tests with a similar format

这可以工作,但速度慢得令人难以置信。我怀疑这是因为每次测试都要重新下载图像。

有没有一种干净的方法来创建一次临时目录,缓存它,并在每次测试中使用该目录的副本?这样,每个测试可以根据需要修改图像,而不影响其他测试,同时保持性能。

2 个评论
如果答案是否定的,那么你可以对夹具进行会话,如果答案是肯定的,那么需要做一些额外的工作。
@gold_cy 是的,图片是就地修改的。
python
caching
pytest
fixtures
FirefoxMetzger
FirefoxMetzger
发布于 2021-02-20
1 个回答
gold_cy
gold_cy
发布于 2021-02-20
已采纳
0 人赞同

因此,实现这一目标的一个可能的解决方案是利用 pytest_sessionstart pytest_sessionfinish .我们还将使用一个夹具,以便将文件复制过来。

我们希望实现的流程的一般分解如下。

  • Download the necessary files before test collection
  • Have the fixture copy the necessary files to a temporary location
  • After the tests complete, delete the files from the cached location
  • 将以下两个钩子放在你的 conftest.py 中,在你的测试所在的根目录下。

    from pathlib import Path
    from tempfile import TemporaryDirectory
    def pytest_sessionstart(session):
        test_imgs = [
            # ... list of img URLs
        td = TemporaryDirectory()
        tmp_path = Path(td.name)
        for idx, im_url in enumerate(test_imgs):
            urllib.request.urlretrieve(im_url, tmp_path / f"{idx}.png")
        session.__IMAGE_CACHE = tmp_path
    def pytest_sessionfinish(session, exitstatus):
        # remove the cached images
        session.__IMAGE_CACHE.cleanup()
    

    现在我们把图片缓存在一个地方,我们可以让我们的夹具在每次测试时把它们复制过来,而不必下载它们。

    from shutil import copytree
    @pytest.fixture
    def image_dir(tmp_path, request):