UnitTest單元測(cè)試框架

UnitTest單元測(cè)試框架

一、單元測(cè)試

  1. 單元測(cè)試概念

    單元測(cè)試(unit testing),是指對(duì)軟件中的最小可測(cè)試單元進(jìn)行檢查和驗(yàn)證

    對(duì)于單元測(cè)試中單元的含義,要根據(jù)實(shí)際情況去判定其具體含義

    一個(gè)單元可能是功能模塊、類、方法(函數(shù))等

  2. 單元測(cè)試工具

    不同的編程語(yǔ)言都有比較成熟的單元測(cè)試框架,語(yǔ)法規(guī)則有些差別,其核心思想都是相通的,常見(jiàn)的單元測(cè)試框架有:

    2.1 Java語(yǔ)言:Junit、TestNG

    2.2 Python語(yǔ)言:UnitTest、Pytest

二、UnitTest框架概念

  1. 介紹

    UnitTest是Python自帶的一個(gè)單元測(cè)試框架,用它來(lái)做單元測(cè)試。也經(jīng)常應(yīng)用到UI自動(dòng)化測(cè)試和接口自動(dòng)化測(cè)試中,用來(lái)管理和維護(hù)測(cè)試用例腳本。

  2. 使用UnitTest框架的好處

    2.1 能夠組織多個(gè)用例去執(zhí)行(可以把多條測(cè)試用例封裝成一個(gè)測(cè)試套件,實(shí)現(xiàn)批量執(zhí)行測(cè)試用例)

    2.2 提供了豐富的斷言方法,方便對(duì)用例執(zhí)行的結(jié)果進(jìn)行判斷

    2.3 能夠生成HTML格式的測(cè)試報(bào)告

    2.4 使用Fixture功能可以減少代碼的冗余

  3. UnitTest核心要素

    3.1 TestCase:測(cè)試用例

    3.2 TestSuite:測(cè)試套件,多條測(cè)試用例集合在一起

    3.3 TestRunner:執(zhí)行測(cè)試用例和測(cè)試套件

三、UnitTest使用

1. TestCase測(cè)試用例

  1. 案例

    1.1 定義一個(gè)實(shí)現(xiàn)加法操作的函數(shù),并對(duì)該函數(shù)進(jìn)行測(cè)試

    # test01_add.py
    import unittest
    
    def add(x, y):
        return x + y
    
    # 必須要集成TestCase類
    class TestAdd(unittest.TestCase):
    
        # 定義測(cè)試方法1
        def test01_add(self):
            result = add(1, 1)
            print('result1=', result)
    
       # 定義測(cè)試方法2
        def test02_add(self):
            result = add(2, 2)
            print('result2=', result)
    
    

    1.2 如何執(zhí)行測(cè)試用例

    使用pycharm在代碼上點(diǎn)擊鼠標(biāo)右鍵,選擇使用UnitTest運(yùn)行

2. TestSuite

  1. 說(shuō)明

    測(cè)試套件可以將多條測(cè)試用例集合在一起,就是一個(gè)TestSuite使用

  2. 使用

    2.1 實(shí)例化:suite = unittest.TestSuite() (suite:為T(mén)estSuite實(shí)例化的名稱)

    2.2 添加用例:suite.addTest(ClassName("MethodName"))(ClassName:為類名;MethodName:為方法名)

    2.3 添加擴(kuò)展:suite.addTest(unittest.makeSuite(ClassName))(搜索指定ClassName內(nèi)test開(kāi)頭的方法并添加到測(cè)試套件中)

    注:TestSuite需要配合TestRunner才能被執(zhí)行

3. TextTestRunner

  1. 說(shuō)明

    TextTestRunner是用來(lái)執(zhí)行測(cè)試用例和測(cè)試套件的使用

  2. 使用流程

    2.1 實(shí)例化:runner = unittest.TextTestRunner()

    2.2 .執(zhí)行:runner.run(suite) suite:為測(cè)試套件名稱

  3. 綜合示例

    3.1 創(chuàng)建第2個(gè)測(cè)試模塊:test_login.py

    # test02_login.py
    import unittest
    
    class TestLogin(unittest.TestCase):
        def test01_login_case(self):
            print("username is wrong")
            
        def test02_login_case(self):
            print('password is wrong')
            
        def test03_login_case(self):
            print('login success')
    

    3.2 同時(shí)運(yùn)行多個(gè)測(cè)試模塊的測(cè)試用例:run_suite.py

    # run_suite.py
    # 添加多個(gè)測(cè)試套件,運(yùn)行測(cè)試用例
    
    import unittest
    from test01_add import TestAdd
    from test02_sub import TestLogin
    
    #實(shí)例化測(cè)試套件對(duì)象
    suite = unittest.TestSuite()
    
    # 添加測(cè)試用例
    suite.addTest(TestAdd("test01_add"))
    suite.addTest(TestAdd("test02_add"))
    suite.addTest(unittest.makeSuite(TestLogin))
    
    #實(shí)例化運(yùn)行器對(duì)象
    runner = unittest.TextTestRunner()
    
    #運(yùn)行測(cè)試套件
    runner.run(suite)
    

4. Fixture

  1. 說(shuō)明

    Fixture是對(duì)一個(gè)測(cè)試用例環(huán)境的初始化和銷毀操作

  2. 方法級(jí)別使用

    2.1 初始化 ( 前置處理 )

    def setUp(self) --> 首先自動(dòng)執(zhí)行

    2.2 銷毀 ( 后置處理 )

    def tearDown(self) --> 最后自動(dòng)執(zhí)行

    2.3 運(yùn)行于測(cè)試方法的始末,

    即:運(yùn)行一次測(cè)試方法就會(huì)運(yùn)行一次 setUp 和 tearDown

  3. 類級(jí)別的使用

    3.1 初始化 ( 前置處理 ):

    @classmethod

    def setUpClass(cls): --> 首先自動(dòng)執(zhí)行

    3.2 銷毀 ( 后置處理 ):

    @classmethod

    def tearDownClass(cls): --> 最后自動(dòng)執(zhí)行

    3.3 運(yùn)行于測(cè)試類的始末,

    即:每個(gè)測(cè)試類只會(huì) 運(yùn)行一次 setUpClass 和 tearDownClass

  4. 示例

    4.1 模擬達(dá)達(dá)商城注冊(cè)模塊自動(dòng)化測(cè)試用例-類級(jí)別的fixture

    import unittest
    
    class TestFixture(unittest.TestCase):
        # 類級(jí)別,初始化、前置處理,測(cè)試開(kāi)始時(shí)只執(zhí)行一次
        @classmethod
        def setUpClass(cls):
            print('自動(dòng)打開(kāi)瀏覽器并進(jìn)入注冊(cè)頁(yè)')
    
        # 類級(jí)別,銷毀、后置處理,測(cè)試結(jié)束時(shí)只執(zhí)行一次
        @classmethod
        def tearDownClass(cls):
            print('自動(dòng)關(guān)閉瀏覽器,執(zhí)行測(cè)試收尾工作')
    
        def test01_register(self):
            # 測(cè)試用例1:注冊(cè)時(shí)用戶名格式輸入錯(cuò)誤
            print('refresh register html')
            print('test01: username is error')
    
        def test02_register(self):
            # 測(cè)試用例2:注冊(cè)時(shí)手機(jī)號(hào)填寫(xiě)錯(cuò)誤
            print('refresh register html')
            print('test02: mobile is error')
    
        def test03_register(self):
            # 測(cè)試用例3:注冊(cè)時(shí)密碼格式填寫(xiě)錯(cuò)誤
            print('refresh register html')
            print('test03: password length is error')
    
        def test04_register(self):
            # 測(cè)試用例4:注冊(cè)時(shí)郵箱格式填寫(xiě)錯(cuò)誤
            print('refresh register html')
            print('test04: email is error')
    

    4.2 模擬達(dá)達(dá)商城登錄模塊自動(dòng)化測(cè)試用例-方法級(jí)別的fixture

    import unittest
    
    class TestLoginFixture(unittest.TestCase):
    
        # 每個(gè)測(cè)試方法執(zhí)行時(shí)都會(huì)執(zhí)行此函數(shù)
        def setUp(self):
            print('自動(dòng)化打開(kāi)了瀏覽器')
    
        # 每個(gè)測(cè)試方法結(jié)束時(shí)都會(huì)執(zhí)行次函數(shù)
        def tearDown(self):
            print('自動(dòng)化關(guān)閉了瀏覽器')
    
        def test01_login(self):
            # 用戶名輸入錯(cuò)誤
            print('username is not exists')
    
        def test02_login(self):
            # 密碼輸入錯(cuò)誤
            print('password is wrong')
    
        def test03_login(self):
            # 都正確,登錄成功
            print('congratulations, login success')
    

5. UnitTest斷言

  1. 說(shuō)明

    讓程序代替人為判斷測(cè)試程序執(zhí)行結(jié)果是否符合預(yù)期結(jié)果的過(guò)程

    UnitTest 中提供了非常豐富的斷言方法,但是常用的也就那么幾個(gè),并且使用起來(lái)也比較簡(jiǎn)單

  2. 斷言方法

  1. 使用示例

    斷言方法經(jīng)在unittest.TestCase 類中定義好了,而且我們自定義的測(cè)試類已經(jīng)繼承了 TestCase ,所以在測(cè)試方法中直接調(diào)用即可。

    import unittest
    
    def add(x, y):
        return x + y
    
    class TestAssert(unittest.TestCase):
        def setUp(self):
            print('方法初始化操作')
    
        def tearDown(self):
            print('方法收尾操作')
    
        def test01(self):
            # 測(cè)試用例1
            result = add(1, 1)
            self.assertEqual(2, result)
    
        def test02(self):
            # 測(cè)試用例2
            result = add(2, 2)
            is_ok = result == 4
            self.assertTrue(is_ok)
    
        def test03(self):
            result = add(3, 3)
            result = str(result)
            self.assertIn(result, "123456")
    

6. UnitTest參數(shù)化

  1. 說(shuō)明

    1.1 通過(guò)參數(shù)的方式來(lái)傳遞數(shù)據(jù),從而實(shí)現(xiàn)數(shù)據(jù)和腳本分離,也可以把測(cè)試數(shù)據(jù)定義到數(shù)據(jù)文件或者數(shù)據(jù)庫(kù)中

    1.2 針對(duì)同一個(gè)測(cè)試方法,可以實(shí)現(xiàn)用例的重復(fù)執(zhí)行,減少代碼冗余,提高測(cè)試效率

    1.3 unittest測(cè)試框架,本身不支持參數(shù)化,但是可以通過(guò)安裝 unittest 擴(kuò)展插件rameterized 來(lái)實(shí)現(xiàn)

  2. 環(huán)境安裝

    sudo pip3 install parameterized

  3. 使用

    3.1 導(dǎo)包

    from parameterized import parameterized

    3.2 使用裝飾器裝飾需要傳參的測(cè)試用例函數(shù)

    @parameterized.expand([(1,1,2),(2,2,4)])

    def test01_add(self, x, y, expect):

       pass
    
  4. 示例

    import unittest
    from parameterized import parameterized
    
    # 方式二:構(gòu)建測(cè)試數(shù)據(jù)
    def build_data():
        return [('token001', 1),('token002', 2),('token003', 3)]
    
    class TestCarts(unittest.TestCase):
        # 方式一:手動(dòng)定義需要傳參數(shù)據(jù) [(),(),...]
        @parameterized.expand([('token001', 1),('token002', 2)])
        def test01_carts(self, token, number):
            print('test01: token=%s number=%d' % (token, number))
            self.assertEqual(200, {'code':200}.get('code'))
    
        # 方式二:定義函數(shù),生成測(cè)試數(shù)據(jù),可以是從json文件讀取,也可以是從數(shù)據(jù)庫(kù)
        @parameterized.expand(build_data)
        def test02_carts(self, token, number):
            print('test02: token=%s number=%d' % (token, number))
            self.assertEqual(200, {'code':200}.get('code'))
    

7. 生成HTML測(cè)試報(bào)告

  1. 說(shuō)明

    測(cè)試腳本執(zhí)行完后,可以生成以 HTML( 網(wǎng)頁(yè) ) 格式的測(cè)試報(bào)告

  2. 為什么要測(cè)試報(bào)告

    2.1 測(cè)試報(bào)告是本次測(cè)試結(jié)果的體現(xiàn)形態(tài)

    2.2 測(cè)試報(bào)告內(nèi)包含了有關(guān)本次測(cè)試用例的詳情

  3. 使用方法

    使用HTMLTestRunner 生成測(cè)試報(bào)告

    3.1 復(fù)制 HTMLTestRunner.py 文件到項(xiàng)目文件夾

    3.2 導(dǎo)入HTMLTestRunner、unittest 包

    3.3 生成測(cè)試套件

    suite = unittest.TestSuite()

    suite.addTest(TestAdd("test_01"))

    3.4 設(shè)置報(bào)告生成路徑和文件名 file_name = "./report/report.html"

    3.5 打開(kāi)報(bào)告 with open(file_name,'wb') a s f:

    3.6 實(shí)例化 HTMLTestRunner 對(duì)象

    runner = HTMLTestRunner(stream=f,[title],[description])

    參數(shù)說(shuō)明:

       stream :文件流,打開(kāi)寫(xiě)入報(bào)告的名稱及 寫(xiě)入編碼格式 ) 
    
       title : [ 可選參數(shù) ] ,為報(bào)告標(biāo)題 
    
       description : [ 可選參數(shù) ] ,為報(bào)告描 述信息
    

    3.7 執(zhí)行: runner.run(suite)

  4. 使用示例

    # run_suite.py
    # 導(dǎo)包
    import unittest
    from test01_add import TestAdd
    from tools.HTMLTestRunner import HTMLTestRunner
    
    #實(shí)例化測(cè)試套件對(duì)象
    suite=unittest.TestSuite()
    
    # 添加測(cè)試用例
    suite.addTest(unittest.makeSuite(TestAdd))
    
    # 定義測(cè)試報(bào)告存放路徑(提前創(chuàng)建report文件夾)
    report_path = './report/report.html'
    # 打開(kāi)文件流
    with open(report_path, 'wb') as f:
        # 實(shí)例化運(yùn)行器對(duì)象
        runner = HTMLTestRunner(f, title='測(cè)試報(bào)告')
        #運(yùn)行測(cè)試套件
        runner.run(suite)
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容