2017-03-29 168 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爲此對象的屬性。然後,當我對我提供的模擬值運行單元測試時,它會返回我期望的結果。