unittest需要第三方插件ddt來實現數據驅動。數據可以是列表、字典或者JSON文件。
>pip install ddt進行安裝
下面是一個簡單的使用舉例。
import unittest
import ddt
@ddt.ddt
class TestAdd(unittest.TestCase):
@ddt.data([1,2,3],[3,4,7])
@ddt.unpack
def test_add(self,a,b,c):
assert a+b==c
則分別使用提供的兩組數據,執行兩個test。
提供多少組數據,就創建多少個測試方法。這裏創建的測試方法是test_add_1__1__2__3_ 和
test_add_2__3__4__7_ (__main__.TestAdd)。
@ddt.file_data('data.json')實現讀取json數據,內容可以是列表或者字典。
excel數據驅動開發思路:
將讀取出的excle文件中的數據以雙重列表的方式返回,作爲@ddt.data()的參數。
比如:實現一個函數,get_data_from_sheet(excel_file_path,sheet_name)。以雙重列表的方式返回data。@ddt.data(*get_data_from_sheet(excel_file_path,sheet_name))使用數據。
ddt源代碼分析:
下面以處理列表數據爲例來分析,處理字典數據和json數據文件的主要流程是相同的。
ddt(arg=None, **kwargs)中對於每一組數據,執行test_name = mk_test_name(name,getattr(v, "__name__", v),i,fmt_test_name)構造新test函數的名字,其中name是原test函數的名字,v是一組數據,i是這組數據的index,fmt_test_name指定新的test函數的名字的格式。
然後執行add_test(cls,test_name,test_data_docstring,func,*v)基於原test函數func生成將新的test函數test_name,加入原testcase類cls,test_data_docstring 是新的test函數的docstring,v是對應的那組數據。
最後執行delattr(cls, name),刪除原test函數。原test函數已經通過各組數據具體化成了新的test函數,所以已經不需要它了。留着它,執行時會拋出異常,TypeError: test_add() missing 3 required positional arguments: 'a', 'b', and 'c'。
下面來重點看一下生成新test函數的邏輯。
add_test(cls, test_name, test_docstring, func, *args, **kwargs)中setattr(cls, test_name, feed_data(func, test_name, test_docstring, *args, **kwargs))。
feed_data(func, new_name, test_data_docstring, *args, **kwargs)中
@wraps(func)
def wrapper(self):
return func(self, *args, **kwargs)
wrapper.__name__ = new_name
wrapper.__wrapped__ = func
wrapper.__doc__ = test_data_docstring
return wrapper
在原來的test函數func的基礎上使用具體參數值,生成新的test函數,名字是new_name。然後將這個函數作爲一個方法添加到原測試用例類cls中。
爲了方便大家理解,下面我把生成新test函數的邏輯提取出來,寫出下面的簡化實現,以及對其使用的舉例。
#下面兩個函數生成新的test函數
def add_test(cls, test_name, func, *args):
setattr(cls, test_name, feed_data(func, test_name, *args))
def feed_data(func, new_name, *args):
def wrapper(self):
return func(self, *args)
wrapper.__name__ = new_name
return wrapper
#下面是使用舉例
import unittest
class TestAdd(unittest.TestCase):
def test_add(self,a,b,c):
self.assertEqual(a+b,c)
add_test(TestAdd,"test_add_1_1_2_3",TestAdd.test_add,1,2,3)
add_test(TestAdd,"test_add_1_3_4_7",TestAdd.test_add,3,4,7)
delattr(TestAdd,"test_add")
unittest.main(verbosity=2)
'''
運行結果:
Total number of cases:2
test_add_1_1_2_3 (__main__.TestAdd) 1 ... ok
test_add_1_3_4_7 (__main__.TestAdd) 2 ... ok
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
'''