簡體   English   中英

Python中單元測試的最佳實踐 - 多個函數適用於同一對象

[英]Best practices for unit testing in Python - multiple functions apply to same object

我有一堆適用於類似對象的函數,例如表示n維框的Numpy數組:

# 3-D box parameterized as:
#     box[0] = 3-D min coordinate
#     box[1] = 3-D max coordinate
box = np.array([
    [1, 3, 0],
    [4, 5, 7]
])

現在我有一大堆我希望在盒子列表上運行的函數,例如。 volumesintersectionsmallest_containing_box等。在我看來,這是我希望設置它的方式:

# list of test functions:
test_funcs = [volume, intersection, smallest_containing_box, ...]
# manually create a bunch of inputs and outputs
test_set_1 = (
    input = [boxA, boxB, ...], # where each of these are np.Array objects
    output = [
        [volA, volB, ...], # floats I calculated manually
        intersection, # np.Array representing the correct intersection
        smallest_containing_box, # etc.
    ]
)
# Create a bunch of these, eg. test_set_2, test_set_3, etc. and bundle them in a list:
test_sets = [test_set_1, ...]
# Now run the set of tests over each of these:
test_results = [[assertEqual(test(t.input), t.output) for test in test_funcs] for t in test_sets]

我想以這種方式構造它的原因是我可以創建多組(輸入,答案)對,並且只對每個對運行所有測試。 除非我有所遺漏,否則unittest的結構似乎不適用於這種方法。 相反,似乎要我為每對函數和輸入創建一個單獨的TestCase對象,即

class TestCase1(unittest.TestCase):
    def setUp(self):
        self.input = [...]
        self.volume = [volA, volB, ...]
        self.intersection = ...
        # etc.

    def test_volume(self):
        self.assertEqual(volume(self.input), self.volume)

    def test_intersection(self):
        self.assertEqual(intersection(self.input), self.output)

    # etc.

# Repeat this for every test case!?

這似乎是一個瘋狂的樣板。 我錯過了什么嗎?

讓我們試着描述我如何理解你的方法:你已經實現了許多具有相似性的不同函數,即它們對相同類型的輸入數據進行操作。 在測試中,您嘗試利用這種相似性:創建一些輸入數據並將該輸入數據傳遞給所有函數。

這種以測試數據為中心的方法是不尋常的。 典型的單元測試方法是以代碼為中心的。 原因是,單元測試的一個主要目標是找到代碼中的錯誤。 不同的功能(顯然)具有不同的代碼,因此錯誤的類型可能不同。 因此,通常仔細設計測試數據以識別相應代碼中的某些類型的錯誤。 測試設計方法是有條理地設計測試用例的方法,理想情況下可以檢測到所有可能的錯誤。

我懷疑使用以測試數據為中心的方法,您將同樣成功地找到不同函數中的錯誤:對於volume函數,可能存在不適用於intersectionsmallest_containing_box溢出方案(以及下溢方案)。 相反,將必須有空的交集,單點交集等。因此,似乎每個功能可能都需要專門設計的測試方案。

關於似乎是以代碼為中心的單元測試的結果的樣板代碼:有幾種方法可以限制這種情況。 你同意,對於不同的測試功能,你會有不同的測試方法。 但是,您可以使用參數化測試來避免進一步的代碼重復。 並且,對於您仍然看到使用(至少有時)不同功能的常見測試數據的優勢的情況:對於這種情況,您可以使用創建測試數據的工廠函數,並且可以從不同的測試用例調用。 例如,您可以從不同的測試中使用工廠函數make-unit-cube

嘗試unittest.TestSuite() 這為您提供了一個可以添加測試用例的對象。 在您的情況下,創建套件,然后遍歷您的列表,創建TestCase實例,它們都只有一個測試方法。 將測試數據傳遞給構造函數並將其保存到那里的屬性而不是setUp()

當您在一個名為suite()的方法中創建suite()並運行所有套件時,單元測試運行器將檢測該套件。

注意:為每個TestCase實例指定一個名稱,或找出哪個失敗將非常困難。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM