[英]unittest.TestCase setUpClass override and inheritance
[英]Python unittest TestCase with inheritance
目前我有許多類似的單元測試測試用例。 每個測試用例都包含數據(輸入值 + 預期輸出值)和邏輯(調用 SUT 並將實際輸出與預期輸出進行比較)。
我想將數據與邏輯分開。 因此我想要一個只包含邏輯的基類和一個只包含數據的派生類。 到目前為止,我想出了這個:
import unittest
class MyClass():
def __init__(self, input):
self.input = input
def get_result(self):
return self.input * 2
class TestBase(unittest.TestCase):
def check(self, input, expected_output):
obj = self.class_under_test(input)
actual_output = obj.get_result()
self.assertEqual(actual_output, expected_output)
def test_get_result(self):
for value in self.values:
self.check(value[0], value[1])
class TestMyClass(TestBase):
def __init__(self, methodName='runTest'):
unittest.TestCase.__init__(self, methodName)
self.class_under_test = MyClass
self.values = [(1, 2), (3, 6)]
unittest.main(exit = False)
但這失敗並出現以下錯誤:
AttributeError: 'TestBase' object has no attribute 'values'
兩個問題:
這里有點晚,但最近開始需要單元測試繼承
我能找到的最優雅的解決方案是:
首先 - 你需要一個基礎測試類
class MyBaseUnitTest(unittest.TestCase):
__test__ = False
def test_someting(self):
...
def test_something_else(self):
...
然后繼承該類並運行測試:
class TestA(MyBaseUnitTest):
__test__ = True
def test_feature(self):
pass
def test_feature2(self):
pass
這是擁有單個視圖集繼承的最佳且最簡單的方法。
我在多重繼承中發現的問題是,當您嘗試調用setUp()
等方法時,它不會在基測試類上調用,因此您必須在您編寫的每個擴展基類的類中調用它。
我希望這會在將來的某個地方幫助某人。
順便說一句:這是在 python3 中完成的 - 我不知道它在 python2 中會如何反應
更新:
這可能更好,更pythonic
class MyBaseUnitTest(object):
def test_someting(self):
...
def test_something_else(self):
...
class TestA(MyBaseUnitTest, unittest.TestCase):
def test_feature(self):
pass
def test_feature2(self):
pass
只要基礎測試類不擴展“unittest.TestCase”,測試運行器就不會解析這些測試,它們也不會在套件中運行。 它們只會在基類擴展它們的地方運行。
要使這項工作按預期進行,您至少需要:
__init__(self, methodName="runTest")
super(TestMyClass, self).__init__(methodName)
def test_get_result(self):
至於它是否是好的設計,請記住,您的測試在一定程度上充當了您的代碼如何工作的文檔。 如果您將所有工作都隱藏在 TestCase 實例狀態中,那么它的作用就不會那么明顯了。 比方說,編寫一個具有接受輸入和預期輸出的自定義斷言的 mixin 類可能會更好。
設計(或多或少)很好——一個“小問題”是當 unittest 查看所有TestCase 類並運行以“test”開頭的方法時。 此時您有幾個選擇。
一種方法是指定被測和價值類作為類屬性。 在這里,如果可能的話,你會希望這些值是不可變的......
class TestBase(unittest.TestCase):
def check(self, input, expected_output):
obj = self.class_under_test(input)
actual_output = obj.get_result()
self.assertEqual(actual_output, expected_output)
def check_all(self):
for value in self.values:
self.check(value[0], value[1])
class TestMyClass1(TestBase):
values = ((1, 2), (3, 4))
class_under_test = MyClass1
def test_it(self):
self.check_all()
class TestMyClass2(TestBase):
values = (('a', 'b'), ('d', 'e'))
class_under_test = MyClass2
def test_it(self):
self.check_all()
你打了兩次test_get_result()
。 我認為TestBase
中根本不應該有任何test*()
方法。 相反,使用TestBase
提供自定義斷言、錯誤格式化程序、測試數據生成器等,並將實際測試保存在TestMyClass
。
Python 的unittest.main()
執行來自當前命名空間中所有測試類的所有測試。
不直接在基類中運行測試的一種方法是將其移動到不同的模塊(例如將TestBase
移動到testbase.py
):
在調用unittest.main()
的文件中,確保不要將該類導入您的命名空間(不要使用from testbase import *
或類似的):
import testbase
class TestMyClass1(testbase.TestBase):
values = ((1, 2), (3, 4))
class_under_test = MyClass1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.