1. 相關的fixture
1.1. tmp_path
tmp_path是一個用例級別的fixture,其作用是返回一個唯一的臨時目錄對象(pathlib.Path);
我們看下面的例子:
# src/chapter-6/test_tmp_path.py
CONTENT = "content"
def test_create_file(tmp_path):
d = tmp_path / "sub"
d.mkdir() # 創建一個子目錄
p = d / "hello.txt"
p.write_text(CONTENT)
assert p.read_text() == CONTENT
assert len(list(tmp_path.iterdir())) == 1 # iterdir() 迭代目錄,返回迭代器
assert 0 # 為了展示,強制置為失敗
執行:
λ pipenv run pytest -q -s src/chapter-6/test_tmp_path.py
F
==================================== FAILURES =====================================
________________________________ test_create_file _________________________________
tmp_path = WindowsPath('C:/Users/luyao/AppData/Local/Temp/pytest-of-luyao/pytest-4/test_create_file0')
def test_create_file(tmp_path):
d = tmp_path / "sub"
d.mkdir() # 創建一個子目錄
p = d / "hello.txt"
p.write_text(CONTENT)
assert p.read_text() == CONTENT
assert len(list(tmp_path.iterdir())) == 1 # iterdir() 迭代目錄,返回迭代器
> assert 0 # 為了展示,強制置為失敗
E assert 0
src\chapter-6\test_tmp_path.py:32: AssertionError
1 failed in 0.06s
可以看出:
tmp_path在不同的操作系統中,返回的是不同類型的pathlib.Path對象,這里Windows系統下返回的是WindowsPath對象,它是Path的子類對象;Path對象可以使用/操作符代替常用的os.path.join()的方法;更多關於pathlib的使用方法可以查看:https://docs.python.org/3.7/library/pathlib.html
1.2. tmp_path_factory
tmp_path_factory是一個會話級別的fixture,其作用是在其它fixture或者用例中創建任意的臨時目錄;
查看上一章tmp_path fixture的源碼,我們能夠看到tmp_path就是使用tmp_path_factory的一個例子:
# _pytest.tmpdir
@pytest.fixture
def tmp_path(request, tmp_path_factory):
"""Return a temporary directory path object
which is unique to each test function invocation,
created as a sub directory of the base temporary
directory. The returned object is a :class:`pathlib.Path`
object.
.. note::
in python < 3.6 this is a pathlib2.Path
"""
return _mk_tmp(request, tmp_path_factory)
@pytest.fixture(scope="session")
def tmp_path_factory(request):
"""Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session.
"""
return request.config._tmp_path_factory
可以看出:
-
tmp_path調用了tmp_path_factory; -
tmp_path_factory返回一個_pytest.tmpdir.TempPathFactory對象; -
進一步查看
_mk_tmp的源碼:def _mk_tmp(request, factory): name = request.node.name name = re.sub(r"[\W]", "_", name) MAXVAL = 30 name = name[:MAXVAL] return factory.mktemp(name, numbered=True)可以看出,
tmp_path最終調用了TempPathFactory.mktemp()方法,它返回的是一個pathlib.Path對象;
1.3. tmpdir
tmp_path是一個用例級別的fixture,其作用是返回一個唯一的臨時目錄對象(py.path.local),它提供os.path的方法;
上面的例子也可以修改成如下這樣:
# src/chapter-6/test_tmpdir.py
CONTENT = "content"
def test_create_file(tmpdir):
p = tmpdir.mkdir("sub").join("hello.txt") # 創建子文件夾,並新建文件
p.write(CONTENT)
assert p.read() == CONTENT
assert len(tmpdir.listdir()) == 1 # iterdir() 迭代目錄,返回列表
assert 0 # 為了展示,強制置為失敗
執行:
λ pipenv run pytest -q -s src/chapter-6/test_tmpdir.py
F
==================================== FAILURES =====================================
________________________________ test_create_file _________________________________
tmpdir = local('C:\\Users\\luyao\\AppData\\Local\\Temp\\pytest-of-luyao\\pytest-6\\test_create_file0')
def test_create_file(tmpdir):
p = tmpdir.mkdir("sub").join("hello.txt") # 創建子文件夾,並新建文件
p.write(CONTENT)
assert p.read() == CONTENT
assert len(tmpdir.listdir()) == 1 # iterdir() 迭代目錄,返回列表
> assert 0 # 為了展示,強制置為失敗
E assert 0
src\chapter-6\test_tmpdir.py:30: AssertionError
1 failed in 0.06s
其實,tmpdir也調用了tmp_path,只是對返回值做了一次py.path.local()封裝:
# _pytest.tmpdir
@pytest.fixture
def tmpdir(tmp_path):
"""Return a temporary directory path object
which is unique to each test function invocation,
created as a sub directory of the base temporary
directory. The returned object is a `py.path.local`_
path object.
.. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html
"""
return py.path.local(tmp_path)
1.4. tmpdir_factory
tmpdir_factory是一個會話級別的fixture,其作用是在其它fixture或者用例中創建任意的臨時目錄;
假設,一個測試會話需要使用到一個很大的由程序生成的圖像文件,相比於每個測試用例生成一次文件,更好的做法是每個會話只生成一次:
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
def test_histogram(image_file):
img = load_image(image_file)
# compute and test histogram
1.5. 區別
| fixture | 作用域 | 返回值類型 |
|---|---|---|
| tmp_path | 用例級別(function) | pathlib.Path |
| tmp_path_factory | 會話級別(session) | TempPathFactory |
| tmpdir | 用例級別(function) | py.local.path |
| tmpdir_factory | 會話級別(session) | TempDirFactory |
2. 默認的基本臨時目錄
上述fixture在創建臨時目錄時,都是創建在系統默認的臨時目錄(例如:Windows系統的%temp%目錄)下;你可以通過指定--basetemp=mydir選項自定義默認的基本臨時目錄;
λ pipenv run pytest -q -s --basetemp="/d/temp" src/chapter-6/test_tmpdir.py
F
==================================== FAILURES =====================================
________________________________ test_create_file _________________________________
tmpdir = local('D:\\temp\\test_create_file0')
def test_create_file(tmpdir):
p = tmpdir.mkdir("sub").join("hello.txt") # 創建子文件夾,並新建文件
p.write(CONTENT)
assert p.read() == CONTENT
assert len(tmpdir.listdir()) == 1 # iterdir() 迭代目錄,返回列表
> assert 0 # 為了展示,強制置為失敗
E assert 0
src\chapter-6\test_tmpdir.py:30: AssertionError
1 failed in 0.04s
