我正在测试一个读取文件的函数,对内容进行操作并根据它看到的内容返回一个值。我测试的函数testme
位于module.py
。我正在运行python 2.7。我知道我可以用
import unittest
import module
from mock import patch, mock_open
TestTestMe(unittest.TestCase):
...
def test_test_me(self):
with patch('module.open', mock_open(read_data='1 2')) as _:
self.assertRaises(IndexError, module.testme, 'foo')
with patch('module.open', mock_open(read_data='1 2 3')) as _:
self.assertEquals(module.testme('foo'), 3)
等
但是,我想(主要是为了防止重复使用with语句,并且还能够动态生成各种read_data)能够使用@patch
作为装饰器来定义带有函数的read_data 。像这样的东西。我不会重复类定义和导入。
def give_contents(x):
if x == 'correct':
return mock_open(read_data='1 2 3')
else:
return mock_open(read_data='a b c')
然后使用测试函数,如:
@patch(module.open, side_effect=give_contents)
def test_test_me(self):
self.assertEquals(module.testme('correct'), 3)
我一直在运行TypeErrors,例如
TypeError: test_testme() takes exactly 1 argument (2 given)
然而,我试图解决这个问题。这真让我抓狂。指导将不胜感激。如果你想要一些我可能已经省略的细节,请询问具体细节,我会提供这些细节。
编辑:按要求执行要测试的功能。对不起,我把它省略为“不重要”,显然应该在那里。
def testme(filepath):
with open(filepath, 'r') as f:
line = f.readline().strip().split()
return int(line[2])
答案 0 :(得分:1)
正如我在之前的评论中所述: 我不确定,因为你没有在你给我们的代码中包含任何test_testme函数。但是,如果它是您正在使用的module.testme方法,则忘记在方法定义中声明字符串参数。根据您的反馈,我可能会给出答案。
编辑:我当时并不完全正确,因为你忘记的论点是自我。
显然,这对你有用,所以这是承诺的答案。
假设您谈到的module.testme方法是一个类似于以下的函数:
TestTestMe(unittest.TestCase):
...
def testme(filepath):
with open(filepath, 'r') as f:
line = f.readline().strip().split()
return int(line[2])
然而,当您从对象访问它时,此函数是一种方法。 (执行module.testme('foo')
),因此,给调用的第一个参数将始终是隐式self
。
所以会发生什么,你的函数期望一个参数,一个字符串(' foo'),但即使自己不是明确的,也会给出两个:'(自我, '富')&#39 ;.
这样的错误就是说你收到的论据比你要求的多。
更正非常简单:将self
添加到testme的预期参数中。
然后会变成:
def testme(self, filepath):
with open(filepath, 'r') as f:
line = f.readline().strip().split()
return int(line[2])
希望这有帮助。关于论证数量的错误实际上通常是由于这种被遗忘的细节。虽然你不需要自我,但它总是作为第一个位置参数传递(在python中)。
祝你有愉快的一天! PS:对不起有些奇怪的英语短语和重复。
答案 1 :(得分:0)
我会考虑以下事项:
from io import TextIOWrapper, BytesIO
from unittest.mock import patch, mock_open
def open_file(filename):
with open(filename, 'r') as f:
data = f.readline()
return data
def string_byte_me(input):
return TextIOWrapper(BytesIO(input))
def side_effect(filename, mode):
if filename == 'correct':
return string_byte_me(b'1 2 3')
else:
return string_byte_me(b'a b c')
m = mock_open()
m.side_effect = side_effect
@patch('builtins.open', m)
def test_open_file():
assert open_file('correct') == '1 2 3'
assert open_file('incorrect') == 'a b c'
test_open_file() # Passes.
这可以通过在实例化之后将side_effect添加到mock_open对象来实现(不确定是否有更好的方法?)。返回的side_effect必须能够.readline()因此是TextIOWrapper。