Python 數據驅動 unittest + ddt


一數據驅動測試的含義:

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

在微軟網站上的解釋是:

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

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

數據驅動測試的環境准備:

  • 測試框架的選擇:在這里選擇的是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語句,我們也可以看到,兩條用例執行時的輸出情況。

數據驅動測試的實例:

上述,我們對數據驅動的使用進行了介紹,接下來,我們一起來看一下在工作中是如何應用的。目前數據驅動,被用在了搜索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)

  

 

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

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




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM