我正在开发一个具有以下架构的项目:
|-- weather
| |-- __init__.py
| |-- weather.py
|-- library
| |-- data.json
|-- test
| |-- __init__.py
| |-- test_weather.py
我想测试执行保存会创建library
目录(如果该目录尚不存在)。 test_weather.py
包含:
import os
import shutil
from weather import weather
def test_library_creation():
# Initialize.
app = weather.WeatherApp()
temp_data = app.get_data()
# Library should not exist initially.
assert not os.path.isdir('library')
app.save(temp_data)
# Library should exist after save.
assert os.path.isdir('library')
assert os.path.isfile(os.path.join('library', 'data.json'))
# Cleanup.
shutil.rmtree('library')
但是,由于运行此测试,我可能不想删除一些保存在data.json
中的数据。
pytest
是否可以解决这种情况?
weather.py
包含:
import os
import json
DEFAULT_SAVE_PATH = os.path.join('library', 'data.json')
class WeatherApp:
def get_data(self):
return dict(temperature=25, humidity=0.5)
def save(self, data, save_path=DEFAULT_SAVE_PATH):
with open('data.json', 'w') as jf:
json.dump(data, jf)
os.renames('data.json', save_path)
答案 0 :(得分:2)
由于您已经考虑过提供自定义保存路径,因此,如果您不想的话,甚至不需要模拟任何内容。只需传递从tmp_path
固定装置派生的自定义路径即可:
def test_library_creation(tmp_path):
app = weather.WeatherApp()
temp_data = app.get_data()
lib_dir = tmp_path / 'library'
# this check is somewhat redundant because pytest will ensure
# the temp dir is created from scratch and is empty
assert not lib_dir.is_dir()
app.save(temp_data, save_path=str(lib_dir / 'data.json'))
# Library should exist after save.
assert lib_dir.is_dir()
assert (lib_dir / 'data.json').is_file()
shutil.rmtree(str(lib_dir))
一些注意事项:
仅在3.6版之前的Python版本中才需要对类似路径的对象进行字符串转换。如果您使用3.6或3.7,则可以直接使用类似路径的对象,例如
app.save(temp_data, save_path=lib_dir / 'data.json')
或
shutil.rmtree(lib_dir)
请注意,os.rename
/ os.renames
在更改文件系统方面不易出错,例如您在本地ext4分区上写入data.json
,并且save_path
指向CIFS共享,则出现错误。
也许重命名操作是多余的?您可以将数据直接写入save_path
。您只需要确保目标目录首先存在,例如os.makedirs(os.path.dirname(save_path), exist_ok=True)
。
如果断言在测试中失败,则将不执行行shutil.rmtree(str(lib_dir))
;这没什么大不了的,因为tmp_path
是在tmpfs上创建的,无论如何在下次重新启动后将被删除。但是,如果您想自己处理删除操作,则可以在测试拆解中使用自定义夹具进行操作:
import os
import shutil
import pytest
from weather import weather
@pytest.fixture
def lib_dir(tmp_path):
d = tmp_path / 'library'
yield d
shutil.rmtree(str(d))
def test_library_creation(lib_dir):
app = weather.WeatherApp()
temp_data = app.get_data()
assert not lib_dir.is_dir()
app.save(temp_data, save_path=str(lib_dir))
# Library should exist after save.
assert lib_dir.is_dir()
assert (lib_dir / 'data.json').is_file()
现在lib_dir
将被删除,无论测试是否通过。
如果要测试默认参数(在app.save(temp_data)
情况下),则需要在DEFAULT_SAVE_PATH
模块中对weather
常量进行猴子修补。使用monkeypatch
固定装置非常简单:
def test_library_creation(monkeypatch, lib_dir):
app = weather.WeatherApp()
temp_data = app.get_data()
assert not lib_dir.is_dir()
with monkeypatch.context() as m:
m.setattr(weather, 'DEFAULT_SAVE_PATH', os.path.join(lib_dir, 'data.json'))
app.save(temp_data)
# Library should exist after save.
assert lib_dir.is_dir()
assert (lib_dir / 'data.json').is_file()