python-3.x - Pytest unittest 函数不返回任何值
问题描述
您能帮我理解以下单元测试的问题吗?这是我正在为其编写单元测试的函数。
def running_config_from_database(device):
try:
data = databaseproxy(cluster='https://xxx.xxxx.xxx.net')
datadb = 'test'
query = f'''fGetrunningconfigData('{device}')
'''
raw_data = data.execute_query(datadb, query)
# pdb.set_trace()
for items in raw_data.fetchall():
config = items['Config'].split('\r\n')
for index, line in enumerate(config):
if '$PASS$' in line:
if line.startswith('set groups ospf_test'):
config_line = line.replace('$PASS$', get_auth('ospf'))
config[index] = config_line
elif line.startswith('set groups rip_test'):
config_line = line.replace('$PASS$', get_auth('rsvp'))
config[index] = config_line
config = config + overload_config
return True, '\r\n'.join(config)
except Exception as e:
return False, f'Failed to get the running config from database, error: {e}'
这是我对此功能的单元测试:
@patch("scripts.test.overload_config")
@patch("scripts.test.get_auth")
@patch("scripts.test.databaseproxy.execute_query")
def test_running_config_from_database(self, mock_data, mock_cred, mock_overload):
ret = MagicMock()
ret.fetchall.return_value = [{'Hostname': 'devA', 'Config': 'set groups ospf_test secret $PASS$\r\n'}]
mock_data.return_value = ret
mock_cred.return_value = 'xyz'
mock_overload = ['sample_overload_config1', 'sample_overload_config2']
expected = ['set groups ospf_test secret xyz', '']
out = expected + mock_overload
data = '\r\n'.join(out)
status, out1 = tests.test_scripts.running_config_from_database('devA')
assert status and out1 == data
当我运行这个 unittest 来测试函数时,我得到以下断言错误 - 看起来函数没有返回任何值。
@patch("scripts.test.overload_config")
@patch("scripts.test.get_auth")
@patch("scripts.test.databaseproxy.execute_query")
def test_running_config_from_database(self, mock_data, mock_cred, mock_overload):
ret = MagicMock()
ret.fetchall.return_value = [{'Hostname': 'devA', 'Config': 'set groups ospf_test secret $PASS$\r\n'}]
mock_data.return_value = ret
mock_cred.return_value = 'xyz'
mock_overload = ['sample_overload_config1', 'sample_overload_config2']
expected = ['set groups ospf_test secret xyz', '']
out = expected + mock_overload
data = '\r\n'.join(out)
status, out1 = tests.test_scripts.running_config_from_database('devA')
> assert status and out1 == data
E AssertionError: assert (True and '' == 'set groups d...rload_config2'
E + set groups ospf_test secret xyz
E +
E + sample_overload_config1
E + sample_overload_config2)
tests/test_scripts.py:80: AssertionError
我编辑了我的函数以降低复杂性,但它仍然不起作用。不知道为什么。
Main Function:
===============
def running_config_from_database(device):
try:
pdb.set_trace()
config = running_config_database(device)
for index, line in enumerate(config):
if '$PASS$' in line:
if line.startswith('set groups ospf_test'):
config_line = line.replace('$PASS$', get_cred('ospf'))
config[index] = config_line
config = config + overload_config
return True, '\r\n'.join(config)
except Exception as e:
return False, f'Failed to get the running config from Database, error: {e}'
上述功能的单元测试结果:
=========================================================================================================== FAILURES ============================================================================================================
________________________________________________________________________________________________ test_running_config_from_database _________________________________________________________________________________________________
mock_cred = <MagicMock name='get_cred' id='140210277622336'>, mock_overload = ['sample_overload_config1', 'sample_overload_config2'], mock_running_config = <MagicMock name='running_config_database' id='140210277652128'>
@patch("test.test1.scripts.running_config_database")
@patch("test.test1.scripts.overload_config")
@patch("test.test1.scripts.get_cred")
def test_running_config_from_database(mock_cred, mock_overload, mock_running_config):
mock_running_config.return_value = ['set groups ospf_test secret $PASS$', '']
mock_cred.return_value = 'xyz'
mock_overload = ['sample_overload_config1', 'sample_overload_config2']
expected = ['set groups ospf_test secret xyz', '']
out = expected + mock_overload
data = '\r\n'.join(out)
status, out1 = test.test1.scripts.test_running_config_from_database('devA')
> assert status and out1 == data
E AssertionError: assert (True and '' == 'set groups d...rload_config2'
E + set groups ospf_test secret xyz
E +
E + sample_overload_config1
E + sample_overload_config2)
validation_tests/test_scripts.py:152: AssertionError
================================================================================================== 1 failed, 6 passed in 4.79s ==================================================================================================
解决方案
这里的问题是分配给mock_overload
. 如果要调整模拟对象,则必须确保对象本身已更改。如果您只是分配另一个对象(在本例中为列表),您的变量现在指向列表对象,而原始对象mock_overload
不再被引用(并且没有更改)。所以不要写:
mock_overload = ['sample_overload_config1', 'sample_overload_config2']
你可以例如写
mock_overload[:] = ['sample_overload_config1', 'sample_overload_config2']
为了清楚起见,这里是原始代码的简化版本:
>>> mock_overload = []
>>> id(mock_overload)
1477793866440
>>> mock_overload = [5, 6]
>>> id(mock_overload)
1477791015560 <- changed id, no longer pointing to the mock
现在与固定代码相同:
>>> mock_overload = []
>>> id(mock_overload)
140732764763024
>>> mock_overload[:] = [5, 6]
>>> id(mock_overload)
140732764763024 <- unchanged id, still points to the mock
请注意,这mock_overload[:] = [5, 6]
基本上是一个快捷方式:
mock_object.clear()
mock_object.extend([5, 6])
推荐阅读
- bash - 如何使用 shell 脚本回答运行时问题并期待
- ansible - 无法启动 ansibled.service:未找到单元
- excel - 使用 Powershell 进行 Excel 操作
- javascript - 如何重构重复的条件 Vue.js 代码?
- python - 如何在没有输出列的新文件上使用此机器学习模型?
- python - 我对教程 djangogirls 的结尾有疑问 https://tutorial.djangogirls.org/fr/django_forms/
- .htaccess - 检查是否在 htaccess 中设置了规范标头
- nginx - Nginx反向代理多个位置未加载
- angularjs - AngularJs 部署站点 SyntaxError:意外的标识符
- micropython - 在 Pybricks-MicroPython 中,stalled() 函数是如何工作的