2016-11-18 71 views
0

假設我在我的項目中的兩個Python模塊:嚴格的報告的代碼覆蓋率

/project 
    /module1 
    __init__.py [Empty] 
    class1.py 
    /module2 
    __init__.py [Empty] 
    class2.py 

Class1有一定的功能,但重要的是doEverythingAndGetData()。讓我們假裝它在執行幾個內部函數時返回一個數字。

現在假設Class2使用Class1,然後實現了其他功能。 Class2只有兩個功能 - __init__foo()

def foo(self): 
    #Create an instance of Class1 
    class1 = Class1() 

    #Get some information using class1 
    data = class1.doEverythingAndGetData() 

    #Do some logic on the data, it doesn't matter 
    result = (data + 10) * 2 

    #Return the result 
    return result 

現在我想寫一個包含foo()的Class2的單元測試。

def test_Class2_foo(): 
    #Create the Class2 object 
    class2 = Class2() 

    #Get the result 
    bar = class2.foo() 

    #Compare the value 
    expectedBar = 1337 
    assert expectedBar == bar, "Mismatch! {} != {}".format(expectedBar, bar) 

該單元測試是唯一爲該項目編寫的測試。我們運行單元測試並生成代碼覆蓋率報告。

檢查代碼覆蓋報告後,我們將看到Class2已被很好地覆蓋,因爲我們已經進行了單元測試,並且它正在做它應該做的事情。太棒了!

然而,我們也注意到,Class1也很好地覆蓋,作爲單元測試覆蓋class1.doEverythingAndGetData()和任何它的基礎功能。我們的報告展示了整個項目的精彩內容!將它發送給採購訂單,讓我們儘早週末吧!

雖然這是誤導。我真的想要報告顯示Class2被覆蓋,因爲我們已經編寫了一個可靠地覆蓋模塊的單元測試。我不要希望它顯示Class1被覆蓋,因爲我們沒有任何單元測試,檢查它的內部功能。它只是假設Class1正常工作,如果單元測試失敗,它的描述將不會很有幫助,也不透明,如果Class1是錯誤的。

因此,要簡化:

  • Class2通過單元測試適當覆蓋
  • Class1沒有直接覆蓋,並把該項目在風險
  • 當單元測試運行,並且代碼覆蓋率報告生成,它不正確地顯示模塊以及測試
  • 而是,我想報告顯示t帽子Class2覆蓋,爲foo()明確由測試調用,Class1不是蓋的,因爲它的功能範圍內Class2.foo()

這使我對以下問題稱爲:

  1. 是否有一個方法來防止在覆蓋報告中發生這種情況?
  2. 什麼,如果有的話,是用來指稱這種類型的覆蓋?
  3. 有沒有特定的編碼模式可以幫助防止這個問題?

謝謝!

+0

您需要爲'class1.doEverythingAndGetData()'提供一個虛擬號碼。因此,'doEverythingAndGetData()'函數永遠不會被調用,它只是返回一個值。這叫做'unittest.mock' – martianwars

回答

1

您需要mock來自class1.doEverythingAndGetData()的數據。在您當前的實現中,每當您調用class2的unittest時,該函數內的實際代碼正在運行。像這樣的事情會幫助你,

from mock import patch 
import class1 

@patch('class1.doEverythingAndGetData') 
def test_Class2_foo(self, doEverythingAndGetData): 
    # Let's assume we are mocking 10 as the return value 
    doEverythingAndGetData.return_value = 10 

    class2 = Class2() 

    # This will take mocked value in its implementation 
    bar = class2.foo() 

    #Compare the value 
    expectedBar = 1337 
    assert expectedBar == bar, "Mismatch! {} != {}".format(expectedBar, bar) 

現在你可以寫class1.doEverythingAndGetData()單獨unittest,並得到正確的覆蓋報告!

所以回答您的3個問題,

是否有辦法防止這種情況的覆蓋率報告發生了什麼?

有沒有特定的編碼模式可以幫助防止這個問題?

是的!使用mock

什麼,如果有的話,是用來指稱這種類型的覆蓋?

從某種意義上說,您所做的可以參考integration測試,其中您可以針對一系列輸入組合測試多個功能。另一方面,在unit測試中,您每函數測試,並嘗試查看其工作,而不關心依賴函數是否工作。

+0

你好,謝謝你的詳細回覆。我會嘗試這個解決方案,看看它是否符合我的需求,但它看起來應該是這樣!但是,假設'class1.doEverythingAndGetData()'返回的是比'10'更復雜的對象。對於這種情況,這是否會起作用? – Grassman7z7

+0

是的,你需要相應地模擬數據。嘗試在模擬不同代表性數據的地方進行多個單元測試 – martianwars

相關問題