Python 數據驅動 unittest + ddt

一數據驅動測試的含義:python

在百度百科上的解釋是:
數據驅動測試,即黑盒測試(Black-box Testing),又稱爲功能測試,是把測試對象看做一個黑盒子。利用黑盒測試法進行動態測試時,須要測試軟件產品的功能,不需測試軟件產品的內部結構和處理過程。數據驅動測試注重於測試軟件的功能性需求,也即數據驅動測試使軟件工程師派生出執行程序全部功能需求的輸入條件。數據庫

在微軟網站上的解釋是:數組

數據驅動的單元測試是爲數據源中的每一行重複運行的一種單元測試。
數據驅動的單元測試的經常使用狀況是使用多個輸入值測試 API。不是編寫調用 API 的多個單元測試(每一個單元測試均具備一組新的輸入),也不是在單元測試中建立一個數組並使用循環代碼,而是能夠編寫執行 API 的單個單元測試方法。而後能夠從數據庫表的行中進行數據檢索以便傳遞給該測試方法的連續調用。可使用此技術測試由不一樣用戶(每一個用戶具備不一樣角色)使用的應用程序。對於每一個用戶,數據源中的一行將根據角色指示預期響應。而後,該測試將經過針對每一個用戶運行功能,對該應用程序進行測試,並驗證產生的響應是否與預期響應一致。bash

在測試工做中,針對某一API接口,或者某一個用戶界面的輸入框,須要設計大量相關的用例,每個用例包含實際輸入的各類可能的數據。一般的作法是,將測試數據存放到一個數據文件裏,而後從數據文件讀取,在腳本中循環輸入測試數據,並對結果進行驗證。而該實現方案,按照微軟網站的解釋,並不屬於數據驅動測試。那麼什麼是數據驅動測試呢?接下來咱們一塊兒看一個實例,便一清二楚了。app

數據驅動測試的環境準備:框架

  • 測試框架的選擇:在這裏選擇的是Python開發語言,測試框架使用Unittest和DDT相結合的方式。
    在python中, unittest測試框架以下:
    import unittest
    
    
    class MyTestCase(unittest.TestCase):
    
        def setUp(self):
            '''
            testcase init ...
            :return:
            '''
            print('setup')
    
        def test_sth(self):
            '''
            must use test_***
            :return:
            '''
            print('test something')
    
        def tearDown(self):
            '''
            testcase release ...
            :return:
            '''
            print('teardown')
    
    if __name__ == '__main__':
        unittest.main()
    

     

Unittest框架包含一個test Fixture,test Fixture由三部分組成,setup,testcase和teardown。Setup過程,是測試用例執行前的初始化過程,teardown過程,是在測試用例執行後,對資源進行釋放與回收的過程;而testcase是具體的測試用例。單元測試

  • 引入ddt框架,須要從ddt官網安裝ddt的模塊。安裝ddt模塊後,使用測試驅動框架後,只須要如下幾行代碼:

      

    import unittest
    import ddt
    
    
    @ddt.ddt
    class MyTestCase(unittest.TestCase):
    
        def setUp(self):
            '''
            testcase init ...
            :return:
            '''
            print('setup')
    
        @ddt.data(['t1' ,'r1'] ,
                  ['t2' , 'r2'])
        @ddt.unpack
        def test_sth(self , testdata , expectresult):
            '''
            must use test_***
            :return:
            '''
            print('test something')
            print(colored('%s - %s'%(testdata , expectresult), 'blue'))
    
        def tearDown(self):
            '''
            testcase release ...
            :return:
            '''
            print('teardown')
            print()
    
    if __name__ == '__main__':
        unittest.main()
    

      

首先在頭部導入ddt;其次在測試類前聲明使用ddt(@ddt.ddt); 第三步,在測試方法前,使用@ddt.data和@unpack進行修飾。而測試數據,在data中進行填加,該demo,有兩條測試數據,每條測數據有兩個字段,第一個是測試數據,第二個是指望的測試結果。從代碼中,能夠看到,咱們在測試用例的實體中,並未使用循環。那麼執行後,是什麼樣的效果呢?測試

setup
test something
t1 - r1
teardown

.setup
test something
t2 - r2
teardown

.
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

  

能夠看到,測試結果有兩條測試用例被執行,而非一條測試用例。也就是測試框架,自動將測試數據分在兩條測試用例裏來執行。經過調試的print語句,咱們也能夠看到,兩條用例執行時的輸出狀況。網站

數據驅動測試的實例:ui

上述,咱們對數據驅動的使用進行了介紹,接下來,咱們一塊兒來看一下在工做中是如何應用的。目前數據驅動,被用在了搜索app的自動化測試執行過程當中。應用的場景是,測試時須要在app裏打開不一樣的垂搜,並驗證對應的垂搜頁面被正常打開,此時須要傳入兩個字段,一是垂搜的名稱,二是打開垂搜後,頁面裏的特殊標識,在此,咱們選擇的是HTML5頁面中的xpath。具體的代碼示例以下:

在未使用數據驅動框架以前,測試這個場景時,每一個垂搜單獨實現了一條測試用例,這裏面有18個垂搜,所以以前對應的是18條測試用例,可見重複的代碼量很高。在使用數據驅動框架後,只須要實現一條測試用例就能夠知足需求,同時須要編寫的代碼量很低。關於數據驅動,網上也有不少其餘的解決方案,例如將測試數據寫到excel中,再從excel中讀取數據。而這一過程,須要編寫必定的代碼,使用框架後,徹底省去了這一過程。

 

import unittest
from ddt import ddt, data, unpack
import csv
from pprint import pprint


def add(a, b):
    print('*'*5 ,a, b)
    c = a + b
    print('c' ,c)
    return c

def addstr(a, b):
    c = a + b
    return c


def get_csv_data():
    value_rows = []
    with open('./mfile.csv') as f:
        f_csv = csv.reader(f)       # 忽略表頭
        next(f_csv)
        for r in f_csv:
            value_rows.append([ int(i) for i in r])
    pprint(value_rows)
    return value_rows

def write_csv_data():
    pass

@ddt
class Test(unittest.TestCase):
    @data((1, 1, 2), (1, 2, 3))
    @unpack
    def test_addnum(self, a, b, expected_value):
        self.assertEqual(add(a, b), expected_value)

    @data(*get_csv_data())
    @unpack
    def test_addstr(self, a, b, expected_value):
        self.assertEqual(add(a, b), expected_value)


if __name__ == "__main__":
    suite = unittest.TestLoader().loadTestsFromTestCase(Test)
    unittest.TextTestRunner(verbosity=2).run(suite)

  

 

 
使用數據驅動框架的意義:

- 代碼複用率高。同一測試邏輯編寫一次,能夠被多條測試數據複用,提升了測試代碼的複用率,同時能夠提升測試腳本的編寫效率。- 異常排查效率高。測試框架依據測試數據,每條數據生成一條測試用例,用例執行過程相互隔離,在其中一條失敗的狀況下,不會影響其餘的測試用例。- 代碼的可維護性高。清晰的測試框架,利於其餘測試工程師閱讀,提升了代碼的可維護性。

相關文章
相關標籤/搜索