[英]How to write a pytest to test for opening two separate files in a single function
如何使用 pytest 检查同一 function 中的两个不同文件是否正确打开?
open_two_files.py
def open_two_files(input_filepath, output_filepath):
open_output = open(output_filepath, 'w')
with open(input_filepath, 'r') as open_input:
for line in open_input:
open_output.write('foo')
我用这个答案来建立一个测试
test_open_two_files.py
import pytest
from unittest.mock import patch, mock_open
from open_two_files import *
def test_open_two_files():
open_mock = mock_open()
with patch('open_two_files.open', open_mock, create=True):
open_two_files("input_filepath", "output_filepath")
open_mock.assert_called_with("input_filepath", 'r')
# pytest passes with the following line commented out
open_mock.assert_called_with("output_filepath", 'w')
我得到的错误是
E AssertionError: expected call not found.
E Expected: open('output_filepath', 'w')
E Actual: open('input_filepath', 'r')
如果我注释掉最后一行,则测试通过。 测试似乎只查看文件最后一次打开的时间。 请问如何测试所有出现的文件被打开?
如果您查看assert_called_with
的文档,您将看到:
此方法是断言最后一次调用是以特定方式进行的便捷方式
(强调我的)
您可以使用assert_any_call来检查这些 arguments 的任何调用:
def test_open_two_files():
open_mock = mock_open()
with patch('open_two_files.open', open_mock, create=True):
open_two_files("input_filepath", "output_filepath")
assert open_mock.call_count == 2
open_mock.assert_any_call("input_filepath", 'r')
open_mock.assert_any_call("output_filepath", 'w')
如果您还想检查调用的顺序,则必须分别检查每个调用:
def test_open_two_files():
...
assert open_mock.call_count == 2
assert open_mock.call_args_list[0][0] == ("output_filepath", 'w')
assert open_mock.call_args_list[1][0] == ("input_filepath", 'r')
或者,如果您至少在 Python 3.8 下:
def test_open_two_files():
...
assert open_mock.call_count == 2
assert open_mock.call_args_list[0].args == ("output_filepath", 'w')
assert open_mock.call_args_list[1].args == ("input_filepath", 'r')
(调用 args 的args
和kwargs
属性已在 Python 3.8 中引入)
我创建了一个开源 pytest 夹具来帮助我自动创建断言以在这种情况下节省一些时间。
如果您pip install pytest-mock-generator
,您将获得名为mg
的模拟生成器夹具,可以像这样使用:
def test_open_two_files(mg):
open_mock = mock_open()
with patch('open_two_files.open', open_mock, create=True):
open_two_files("input_filepath", "output_filepath")
open_mock.assert_called_with("input_filepath", 'r')
mg.generate_asserts(open_mock)
然后执行您的测试,夹具将打印到控制台,并将以下内容复制到剪贴板:
from mock import call
assert 2 == open_mock.call_count
open_mock.assert_has_calls(calls=[call('output_filepath', 'w'),call('input_filepath', 'r'),])
open_mock.return_value.__enter__.assert_called_once_with()
open_mock.return_value.__iter__.assert_called_once_with()
open_mock.return_value.__exit__.assert_called_once_with(None, None, None)
您可以将代码按原样插入到测试中,也可以根据需要对其进行修改。 假设您不关心测试上下文的进入和退出,您的最终测试将如下所示:
from unittest.mock import patch, mock_open, call
from open_two_files import *
def test_open_two_files():
open_mock = mock_open()
with patch('open_two_files.open', open_mock, create=True):
open_two_files("input_filepath", "output_filepath")
open_mock.assert_called_with("input_filepath", 'r')
assert 2 == open_mock.call_count
open_mock.assert_has_calls(calls=[call('output_filepath', 'w'),call('input_filepath', 'r'),])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.