unittest的參數化

  • 2019 年 12 月 9 日
  • 筆記

之前寫了很多關於unittest單元測試框架的文章,本小節主要介紹它在參數化方面的應用,首先需要安裝第三方的庫parameterized,安裝的命令為:pip install parameterized。安裝成功後。這裡主要結合具體的案例來說明它的應用和實現的具體細節 ,編寫一個兩個數相加的函數,然後針對該函數來設計具體的測試點,實現的代碼如下:

#!/usr/bin/env python  #author:wuya  from parameterized import  parameterized,param  import unittest    def add(a,b):     return a+b    class AddTest(unittest.TestCase):     @parameterized.expand([        param(1,1,2),        param(1.0,1.0,2.0),        param('hi',' wuya','hi wuya')     ])     def test_add_cases(self,first,second,result):        self.assertEqual(add(first,second),result)    if __name__ == '__main__':      unittest.main(verbosity=2)

執行如上的代碼後,顯示三個測試點都測試通過,parameterized的設計思想有點和ddt相似,至少在參數化方面可以說是思想是一致的。在執行具體的測試點時候,它是對列表裏面的參數進行進行循環然後依次賦值,也就是說,當循環到第一個元組的參數的時候,first其實是1,second是1,result是2,依次循環,這樣就可以使用parameterized,來達到一個測試點的代碼完成N個測試點的場景的測試。當然上面的不是很完善的。具體對代碼打斷點,來看賦值的具體過程,如下圖所示:

在如上的信息中,可以看到具體循環賦值的過程。當然上面的函數還是不夠完善,至少沒有加異常的處理,那麼需要添加異常,完善後的代碼為:

#!/usr/bin/env python  #author:wuya  from parameterized import  parameterized,param  import unittest    def add(a,b):     try:        return a + b     except Exception as e:        return e.args[0]    class AddTest(unittest.TestCase):     @parameterized.expand([        param(1,1,2),        param(1.0,1.0,2.0),        param('hi',' wuya','hi wuya')     ])     def test_add_cases(self,first,second,result):        self.assertEqual(add(first,second),result)    if __name__ == '__main__':      unittest.main(verbosity=2)

再次執行代碼,依然執行通過。但是我們很清晰的看到,增加異常後,在測試的場景裏面並沒有考慮到異常情況的測試,比如int與str相加會怎麼樣,這樣的測試點沒加,也就意味着add()函數裏面的異常部分並沒有被覆蓋到,具體我們結合coverage來看下,coverage執行的過程具體是執行要測試的代碼,然後是分析,最後是報告,執行的命令分別是:coverage run coverage report coverage html,如下圖顯示命令執行的執行細節:

打開對應的html報告後,可以看到異常的代碼並沒有被覆蓋到,如下圖所示

那麼就需要再次完善測試點,增加對異常的測試點的考慮,完善後的代碼為:

#!/usr/bin/env python  #author:wuya  from parameterized import  parameterized,param  import unittest    def add(a,b):     try:        return a + b     except Exception as e:        return e.args[0]    class AddTest(unittest.TestCase):     @parameterized.expand([        param(1, 1, 2),        param(1.0, 1.0, 2.0),        param(1, 1.0, 2.0),        param(1, 0, 1),        param('', '', ''),        param('hi ', 'wuya', 'hi wuya'),        param(0, '', "unsupported operand type(s) for +: 'int' and 'str'"),        param(1, 'hi', "unsupported operand type(s) for +: 'int' and 'str'"),        param(1.0, 'wuya', "unsupported operand type(s) for +: 'float' and 'str'"),     ])     def test_add_cases(self,first,second,result):        self.assertEqual(add(first,second),result)    if __name__ == '__main__':      unittest.main(verbosity=2)

見如上的代碼,這樣結合coverage以及parameterized的工具,就能夠使用很簡單的代碼對一個函數的代碼都能夠覆蓋到,並且使用一個測試方法就能夠測試很多的測試場景。

感謝您的閱讀和關注,後續文章會持續更新。如您感興趣,也可購買本人的書籍和實戰視頻,謝謝!