Python 3.x Pytest unittest函数没有';不返回任何值

Python 3.x Pytest unittest函数没有';不返回任何值,python-3.x,pytest,Python 3.x,Pytest,你们能帮我理解下面单元测试的问题吗? 下面是我正在编写的unittest函数 def从_数据库(设备)运行_config_: 尝试: 数据=数据库代理(群集服务器)https://xxx.xxxx.xxx.net') datadb='test' query=f'''fGetrunningconfigData('{device}') ''' 原始数据=数据。执行查询(datadb,查询) #pdb.set_trace() 对于原始数据中的项。fetchall() config=items['con

你们能帮我理解下面单元测试的问题吗? 下面是我正在编写的unittest函数

def从_数据库(设备)运行_config_:
尝试:
数据=数据库代理(群集服务器)https://xxx.xxxx.xxx.net')
datadb='test'
query=f'''fGetrunningconfigData('{device}')
'''
原始数据=数据。执行查询(datadb,查询)
#pdb.set_trace()
对于原始数据中的项。fetchall()
config=items['config'].split('\r\n')
对于索引,枚举(配置)中的行:
如果行中有“$PASS$”:
如果line.startswith('set groups ospf_test'):
config_line=line.replace(“$PASS$”,get_auth('ospf'))
配置[索引]=配置行
elif line.startswith('set groups rip_test'):
config_line=line.replace(“$PASS$”,get_auth('rsvp'))
配置[索引]=配置行
配置=配置+重载配置
返回True,'\r\n'。加入(配置)
例外情况除外,如e:
返回False,f'未能从数据库中获取正在运行的配置,错误:{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 ==================================================================================================
============================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================
________________________________________________________________________________________________测试\u从\u数据库运行\u config\u_________________________________________________________________________________________________
mock\u cred=,mock\u重载=['sample\u重载\u config1','sample\u重载\u config2',mock\u running\u config=
@补丁(“test.test1.scripts.running\u config\u database”)
@补丁(“test.test1.scripts.overload\u config”)
@补丁(“test.test1.scripts.get_cred”)
def test_running_config_来自_数据库(mock_cred、mock_重载、mock_running_config):
mock_running_config.return_value=[“设置组ospf_测试机密$PASS$”,“”]
模拟信任返回值='xyz'
模拟过载=['sample\u过载\u配置1','sample\u过载\u配置2']
预期=['set groups ospf_test secret xyz','']
输出=预期+模拟负载
数据='\r\n'。加入(输出)
状态,out1=test.test1.scripts.test\u从数据库('devA')运行配置
>断言状态和out1==数据
E AssertionError:assert(True和“”='设置组d…rload_config2'
E+集组ospf_测试秘密xyz
E+
E+样本\u过载\u配置1
E+样本\过载\配置2)
验证测试/测试脚本。py:152:AssertionError
====================================================================================================================================================================================================================================1次失败,6次在4.79秒内通过==================================================================================================

答案已由@MrBean breme在评论部分提供。下面是建议进行更改后的UT

@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

这里的问题是对
mock\u重载的赋值。如果要调整模拟对象,必须确保对象本身已更改。如果您只分配了另一个对象(在本例中为列表),那么您的变量现在将指向列表对象,而原始的
mock_重载
将不再被引用(并且不会更改)。因此,与其写:

mock_-overload=['sample_-overload_-config1','sample_-overload_-config2']
例如,你可以写

mock\u-overload[:]=['sample\u-overload\u-config1','sample\u-overload\u-config2']
为了澄清,以下是原始代码的简化版本:

>>> mock_overload = []
>>> id(mock_overload)
1477793866440
>>> mock_overload = [5, 6]
>>> id(mock_overload)
1477791015560  <- changed id, no longer pointing to the mock

您模拟
“scripts.test.xxx”
,但调用
tests.test\u scripts。从\u数据库运行\u config\u
。你不应该也模拟
测试。测试脚本.xxx
?另外,你只需重新分配
模拟重载
,因此模拟不被使用-如果它是一个列表,你可能应该改为执行
模拟重载[:]=[…]
。除此之外,在我看来还可以。您是否注意到编写此测试的复杂性随着功能的增加而增加?也许是时候考虑把你的函数分解成更小的部分了,这样函数就可以做一件事,让测试更容易…@beanbremen先生,谢谢你的评论。在粘贴输出之前,我必须编辑函数/单元测试,这就是您看到差异的原因。我嘲笑了所有的依赖关系。@gold_cy,是的,我正在努力,但我想知道,我做错了什么
>>> mock_overload = []
>>> id(mock_overload)
140732764763024
>>> mock_overload[:] = [5, 6]
>>> id(mock_overload)
140732764763024  <- unchanged id, still points to the mock