Pytest:重现 OSError 的单元测试
Pytest: unit test to reproduce OSError
如何重现 OSError 以便我知道我的异常有效?
def write_file():
try:
with open('file.txt', "w+") as f:
f.write("sth")
f.close()
except OSError as e:
logging.error("OSError occured")
我想使用 pytest 为函数 write_file()
编写单元测试。我如何模拟 OSError
?
您想做两件事:
- 使
open()
失败 OSError
。为此,
@pytest.fixture(scope="function")
def change_test_dir(request):
os.chdir('/')
yield
os.chdir(request.config.invocation_dir)
因为我假设您不允许在 /
.
中写入
- 您想测试是否出现了正确的
logging
错误。参见 here
您必须模拟 open()
调用。你可以用 standard library unittest.mock.patch()
function, or with the pytest
monkeypatch
fixture;我个人更喜欢在这里使用标准库:
import pytest
import logging
from unittest import mock
from module_under_test import write_file
def test_write_file_error(caplog):
caplog.clear()
with mock.patch("module_under_test.open") as mock_open:
mock_open.side_effect = OSError
write_file()
assert caplog.record_tuples == [("root", logging.ERROR, "OSError occured")]
mock.patch()
上下文管理器设置在 module_under_test
全局命名空间中放置了一个模拟的 open
对象,屏蔽了内置的 open()
函数。将 side_effect
属性设置为异常可确保调用模拟对象将引发该异常。
模拟 open()
比尝试创建内置 open()
函数会引发异常的确切文件系统环境要容易得多。此外,您正在测试 您自己的代码 如何正确处理 OSError
,而不是 open()
是否按设计工作。
一些旁注:
- 不需要调用
f.close()
;您将打开的文件用作上下文管理器 (with ... as f:
),因此它会自动关闭 ,无论 with
块中发生什么。
- 正确的拼写是 occurred (double r) :-)
- 如果您不打算使用
e
异常引用,请不要使用 except OSError as e:
;删除 as e
部分。
- 如果您使用
logging.exception()
function,那么异常和完整的回溯将被捕获在日志中,作为 ERROR
级别的消息。
def write_file():
try:
with open('file.txt', "w+") as f:
f.write("sth")
except OSError:
logging.exception("Failed to write to file.txt")
如何重现 OSError 以便我知道我的异常有效?
def write_file():
try:
with open('file.txt', "w+") as f:
f.write("sth")
f.close()
except OSError as e:
logging.error("OSError occured")
我想使用 pytest 为函数 write_file()
编写单元测试。我如何模拟 OSError
?
您想做两件事:
- 使
open()
失败OSError
。为此,
@pytest.fixture(scope="function")
def change_test_dir(request):
os.chdir('/')
yield
os.chdir(request.config.invocation_dir)
因为我假设您不允许在 /
.
- 您想测试是否出现了正确的
logging
错误。参见 here
您必须模拟 open()
调用。你可以用 standard library unittest.mock.patch()
function, or with the pytest
monkeypatch
fixture;我个人更喜欢在这里使用标准库:
import pytest
import logging
from unittest import mock
from module_under_test import write_file
def test_write_file_error(caplog):
caplog.clear()
with mock.patch("module_under_test.open") as mock_open:
mock_open.side_effect = OSError
write_file()
assert caplog.record_tuples == [("root", logging.ERROR, "OSError occured")]
mock.patch()
上下文管理器设置在 module_under_test
全局命名空间中放置了一个模拟的 open
对象,屏蔽了内置的 open()
函数。将 side_effect
属性设置为异常可确保调用模拟对象将引发该异常。
模拟 open()
比尝试创建内置 open()
函数会引发异常的确切文件系统环境要容易得多。此外,您正在测试 您自己的代码 如何正确处理 OSError
,而不是 open()
是否按设计工作。
一些旁注:
- 不需要调用
f.close()
;您将打开的文件用作上下文管理器 (with ... as f:
),因此它会自动关闭 ,无论with
块中发生什么。 - 正确的拼写是 occurred (double r) :-)
- 如果您不打算使用
e
异常引用,请不要使用except OSError as e:
;删除as e
部分。 - 如果您使用
logging.exception()
function,那么异常和完整的回溯将被捕获在日志中,作为ERROR
级别的消息。
def write_file():
try:
with open('file.txt', "w+") as f:
f.write("sth")
except OSError:
logging.exception("Failed to write to file.txt")