py.test中的tmpdir
fixture使用function
范围,因此在具有更广范围的工具中不可用,例如session
。但是,这对于某些情况很有用,例如设置临时PostgreSQL服务器(当然不应该为每个测试重新创建)。
是否有任何干净的方法可以获得更广泛范围的临时文件夹,而不涉及编写我自己的夹具并访问py.test的内部API?
答案 0 :(得分: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
答案 1 :(得分: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时也会引起问题。
答案 2 :(得分: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
答案 3 :(得分:-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)