2017-03-29 128 views
1

假设我有一个目录单元测试涉及数据库

home/user/my_python_scripts/ 
        /src 
         /my_script.py 
        /tests 
         /test_my_script.py 

我运行一些单元测试,从~/my_python_scripts/test目录测试my_script.py。我从my_script将功能导入到我的test_my_script.py中。

但问题出现了,因为my_script.py中的函数从另一个脚本中导入了两个其他函数。这两个函数查询数据库中的特定数据。我在我的测试脚本中嘲笑和修补这两个函数,但是当我在这个脚本上运行pytest时,函数无论如何都会查询数据库。我看了my_script.py使用的两个函数。他们每个人都查询不同的数据库,而且其中一个功能最终使用三个其他功能,这些功能与它所在的文件相同。

我在单元测试中没有正确考虑这些函数和/或数据库吗?

from pytest_mock import mocker 

params = [(3141, 55)] 
raw_data = [{'a': 'fizz', 'b': 'buzz', 'c': 'foo', 'd': 'hello'}] 
descriptors = ['taxi', 3141, 55, 1] 

def test_get_data(mocker): 
    setattr(get_data, 'get_raw_data', params) 
    mocker.patch.object(get_data, 'get_raw_data') 
    get_data.get_raw_data.return_value = params 
    setattr(get_data, 'get_data_by_day', raw_data) 
    mocker.patch.object(get_data, 'get_data_by_day') 
    get_data.get_data_by_day.return_value = raw_data 
    assert get_data('taxi', 3141, '1', '3') == raw_data, descriptors 

寻找任何意见以及提示:因为它是专有的,但我很乐意分享我下面的单元测试代码,我不能共享代码。

+0

这听起来很像是一个设计问题。 **输入**不应触发实际行动。 – GhostCat

+0

所以你说的其他两个功能的设计方式是有缺陷的。不管如何,除了重写所有其他代码之外,您是否有任何关于如何在这种情况下继续的建议。 –

+1

我没有那么多入python;所以不行。但是,再次;你真的想要一个导入语句触发这样的活动吗?如果有人在他的剧本中偶然发现了这样的进口呢?复制和粘贴始终发生。所以,在我看来,唯一合理的,长期的答案是解决真正的问题;而不是解决它;即使在你的测试设置中。 – GhostCat

回答

1

所以我想通了。我没有正确地设置补丁模拟函数的值。这是最终正常工作的代码。

from mock import patch 
from .relative.path import get_data 

params = [(3141, 55)] 
raw_data = [{'a': 'fizz', 'b': 'buzz', 'c': 'foo', 'd': 'hello'}] 
descriptors = ['taxi', 3141, 55, 1] 

@patch.object(get_data, 'get_raw_data') 
@patch.object(get_data, 'get_data_by_day') 
def test_get_stuff_1(mock_get_data_by_day, mock_get_raw_data): 
    mock_get_data_by_day.return_value = raw_data 
    mock_get_raw_data.return_value = params 
    result = get_data.get_stuff('taxi', 3141, '1', '3') 
    assert result == (raw_data, descriptors) 

我导入脚本get_data.py作为对象,然后修补各功能get_raw_dataget_data_by_day为此对象的属性。然后,当我对我提供的模拟值运行单元测试时,它会返回我期望的结果。