py.test:会话范围的临时文件夹

问题描述 投票:13回答:4

py.test中的tmpdir夹具使用function范围,因此在具有更广范围的夹具中不可用,例如session。但是,这对于某些情况很有用,例如设置临时PostgreSQL服务器(当然不应该为每个测试重新创建)。

是否有任何干净的方法来获得更广泛的范围的临时文件夹,不涉及编写我自己的夹具和访问py.test的内部API?

python pytest
4个回答
13
投票

不幸的是,目前还没有办法做得很好。在未来,py.test将为此引入一个新的“任何”范围或类似的东西,但那是未来。

现在你必须自己手动完成。然而,正如你注意到你松散了一些不错的功能:/ tmp到最后一次测试的符号链接,几次测试运行后的自动清理,合理命名的目录等。如果目录不是太贵我通常会结合会话和功能范围的夹具以下列方式:

@pytest.fixture(scope='session')
def sessiondir(request):
    dir = py.path.local(tempfile.mkdtemp())
    request.addfinalizer(lambda: dir.remove(rec=1))
    # Any extra setup here
    return dir

@pytest.fixture
def dir(sessiondir, tmpdir):
    sessiondir.copy(tmpdir)
    return tmpdir

这将创建一个临时目录,在测试运行后进行清理,但是对于每个实际需要它的测试(通过请求dir)获取一个使用tmpdir语义保存的副本。

如果测试实际上需要通过这个目录共享状态,那么dir的终结器必须将东西复制回sessiondir。然而,这不是一个好主意,因为它使测试依赖于执行顺序,并且在使用pytest-xdist时也会导致问题。


19
投票

由于pytest版本2.8及更高版本,会议范围的tmpdir_factory夹具可用。请参阅下面的documentation示例。

# contents of conftest.py
import pytest

@pytest.fixture(scope='session')
def image_file(tmpdir_factory):
    img = compute_expensive_image()
    fn = tmpdir_factory.mktemp('data').join('img.png')
    img.save(str(fn))
    return fn

# contents of test_image.py
def test_histogram(image_file):
    img = load_image(image_file)
    # compute and test histogram

0
投票

当我想删除会话中创建的所有临时文件夹时,我添加了终结器。

_tmp_factory = None
@pytest.fixture(scope="session")
def tmp_factory(request, tmpdir_factory):
    global _tmp_factory
    if _tmp_factory is None:
        _tmp_factory = tmpdir_factory
        request.addfinalizer(cleanup)
    return _tmp_factory

def cleanup():
    root = _tmp_factory.getbasetemp().strpath
    print "Cleaning all temporary folders from %s" % root
    shutil.rmtree(root)

def test_deleting_temp(tmp_factory):
    root_a = tmp_factory.mktemp('A')
    root_a.join('foo.txt').write('hello world A')

    root_b = tmp_factory.mktemp('B')
    root_b.join('bar.txt').write('hello world B')

    for root, _, files in os.walk(tmp_factory.getbasetemp().strpath):
        for name in files:
            print(os.path.join(root, name))

输出应该是:

/tmp/pytest-of-agp/pytest-0/.lock
/tmp/pytest-of-agp/pytest-0/A0/foo.txt
/tmp/pytest-of-agp/pytest-0/B0/bar.txt
Cleaning all temporary folders from /tmp/pytest-of-agp/pytest-0

-1
投票

这是另一种方法。看起来pytest在测试运行后不会删除临时目录。以下是常规功能范围的夹具。

# conftest.py
TMPDIRS = list()

@pytest.fixture
def tmpdir_session(tmpdir):
    """A tmpdir fixture for the session scope. Persists throughout the session."""
    if not TMPDIRS:
        TMPDIRS.append(tmpdir)
    return TMPDIRS[0]

并且跨模块而不是整个pytest会话拥有持久的临时目录:

# conftest.py
TMPDIRS = dict()

@pytest.fixture
def tmpdir_module(request, tmpdir):
    """A tmpdir fixture for the module scope. Persists throughout the  module."""
    return TMPDIRS.setdefault(request.module.__name__, tmpdir)

编辑:这是另一个不涉及全局变量的解决方案。 pytest 1.8.0引入了一个我们可以使用的tmpdir_factory夹具:

@pytest.fixture(scope='module')
def tmpdir_module(request, tmpdir_factory):
    """A tmpdir fixture for the module scope. Persists throughout the module."""
    return tmpdir_factory.mktemp(request.module.__name__)


@pytest.fixture(scope='session')
def tmpdir_session(request, tmpdir_factory):
    """A tmpdir fixture for the session scope. Persists throughout the pytest session."""
    return tmpdir_factory.mktemp(request.session.name)
© www.soinside.com 2019 - 2024. All rights reserved.