[英]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]
])
現在我有一大堆我希望在盒子列表上運行的函數,例如。 volumes
, intersection
, smallest_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
函數,可能存在不適用於intersection
或smallest_containing_box
溢出方案(以及下溢方案)。 相反,將必須有空的交集,單點交集等。因此,似乎每個功能可能都需要專門設計的測試方案。
關於似乎是以代碼為中心的單元測試的結果的樣板代碼:有幾種方法可以限制這種情況。 你同意,對於不同的測試功能,你會有不同的測試方法。 但是,您可以使用參數化測試來避免進一步的代碼重復。 並且,對於您仍然看到使用(至少有時)不同功能的常見測試數據的優勢的情況:對於這種情況,您可以使用創建測試數據的工廠函數,並且可以從不同的測試用例調用。 例如,您可以從不同的測試中使用工廠函數make-unit-cube
。
嘗試unittest.TestSuite()
。 這為您提供了一個可以添加測試用例的對象。 在您的情況下,創建套件,然后遍歷您的列表,創建TestCase
實例,它們都只有一個測試方法。 將測試數據傳遞給構造函數並將其保存到那里的屬性而不是setUp()
。
當您在一個名為suite()
的方法中創建suite()
並運行所有套件時,單元測試運行器將檢測該套件。
注意:為每個TestCase
實例指定一個名稱,或找出哪個失敗將非常困難。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.