1. 程式人生 > 實用技巧 >一、單元測試unittest

一、單元測試unittest

一、定義

1)什麼是單元測試?

單元:函式或者是類

單元測試:測試類或者函式

2)為什麼做單元測試?

投入小、收益大,能夠精準的、更早的發現問題

3)單元測試和我有什麼關係?

python語言是很難測試java的單元,關鍵是單元測試一般是開發或者測開做的。

自動化測試主要是做:整合測試、系統測試、驗收測試

二、unittest-TestCase

單元測試框架:

Python內建的單元測試框架:unittest

unittest的注意事項:

1.模組名稱:test_開頭

2.類名:Test····

3.測試用例方法名稱:test·····開頭

4.TestLogin(unittest.TestCase),不要忘了繼承unittest.TestCase

#匯入單元測試框架unittest
import unittest

"""測試登入功能(函式)"""
def login(username = None,password = None):
    if username != None and password != None:
        if username == "zjx111" and password == "123456":
            return {"code":0,"msg":"登入成功!"}
        
else: return {"code":1,"msg":"登入失敗,使用者名稱或密碼錯誤!"} else: return {"code":1,"msg":"登入失敗,使用者名稱或密碼為空!"} #設計登入測試用例類 class TestLogin(unittest.TestCase):#繼承unittest.TestCase def test_login_success(self): '''登入成功''' username = "zjx111" password = "123456" expected_reponse
= {"code":0,"msg":"登入成功!"} #實際結果:呼叫login函式 actual_reponse = login(username,password) #判斷預期結果跟實際結果是否一樣 斷言 self.assertTrue(expected_reponse == actual_reponse) def test_login_error(self): '''登入失敗''' username = '' password = '' expected_reponse = {"code":1,"msg":"登入失敗,使用者名稱或密碼錯誤!"} actual_reponse = login(username, password) self.assertTrue(expected_reponse == actual_reponse)

三、unittest-Fixture:測試環境的搭建和銷燬(前置、後置條件)

# 前置、後置條件是固定的名稱,不改,執行一個用例執行一次前置後置條件

def setUp(self):
   '''前置條件'''
   pass
    
def tearDown(self):
   '''後置條件'''
   pass

在用例執行之前執行setUp(),在用例執行之後執行tearDown()
有多少條用例,就執行多少遍setUp()和tearDown()

#匯入單元測試框架unittest
import unittest

"""測試登入功能(函式)"""
def login(username = None,password = None):
    if username != None and password != None:
        if username == "zjx111" and password == "123456":
            return {"code":0,"msg":"登入成功!"}
        else:
            return {"code":1,"msg":"登入失敗,使用者名稱或密碼錯誤!"}
    else:
        return {"code":1,"msg":"登入失敗,使用者名稱或密碼為空!"}

#設計登入測試用例類
class TestLogin(unittest.TestCase):#繼承unittest.TestCase

    def setUp(self):
        '''前置條件'''
        print('連線資料庫')

    def tearDown(self):
        '''後置條件'''
        print('斷開資料庫')

    def test_login_success(self):
        '''登入成功'''
        username = "zjx111"
        password = "123456"
        expected_reponse = {"code":0,"msg":"登入成功!"}

        #實際結果:呼叫login函式
        actual_reponse = login(username,password)
        #判斷預期結果跟實際結果是否一樣   斷言
        self.assertTrue(expected_reponse == actual_reponse)


    def test_login_error(self):
        '''登入失敗'''
        username = ''
        password = ''
        expected_reponse = {"code":1,"msg":"登入失敗,使用者名稱或密碼錯誤!"}
        actual_reponse = login(username, password)
        self.assertTrue(expected_reponse == actual_reponse)

'''
結果:
連線資料庫
斷開資料庫
連線資料庫
斷開資料庫
'''

如果想在一個測試類當中,只執行一次的話前置和後置,需要用到類方法:setUpClass(cls)和tearDownClass(cls)

#匯入單元測試框架unittest
import unittest

"""測試登入功能(函式)"""
def login(username = None,password = None):
    if username != None and password != None:
        if username == "zjx111" and password == "123456":
            return {"code":0,"msg":"登入成功!"}
        else:
            return {"code":1,"msg":"登入失敗,使用者名稱或密碼錯誤!"}
    else:
        return {"code":1,"msg":"登入失敗,使用者名稱或密碼為空!"}

#設計登入測試用例類
class TestLogin(unittest.TestCase):#繼承unittest.TestCase

    @classmethod
    def setUpClass(cls):
        print('一個測試類中只會執行一次的前置條件')

    @classmethod
    def tearDownClass(cls):
        print('一個測試類中只會執行一次的後置條件')

    def setUp(self):
        '''前置條件'''
        print('連線資料庫')

    def tearDown(self):
        '''後置條件'''
        print('斷開資料庫')

    def test_login_success(self):
        '''登入成功'''
        username = "zjx111"
        password = "123456"
        expected_reponse = {"code":0,"msg":"登入成功!"}

        #實際結果:呼叫login函式
        actual_reponse = login(username,password)
        #判斷預期結果跟實際結果是否一樣   斷言
        self.assertTrue(expected_reponse == actual_reponse)


    def test_login_error(self):
        '''登入失敗'''
        username = ''
        password = ''
        expected_reponse = {"code":1,"msg":"登入失敗,使用者名稱或密碼錯誤!"}
        actual_reponse = login(username, password)
        self.assertTrue(expected_reponse == actual_reponse)

'''
結果:
一個測試類中只會執行一次的前置條件
連線資料庫
斷開資料庫
連線資料庫
斷開資料庫
一個測試類中只會執行一次的後置條件
'''    

四、unittest-TestSuite/TextTestRunner:測試套件/執行測試用例

unittest測試用例的執行順序:
不是從上到下
根據測試用例的名稱:ASCII碼
如果想自己調整測試用例的順序,就可以在測試用例的方法名稱上加數字,比如:test_login_01_success(self)

我們會把測試用例的程式碼放到一個統一的資料夾當中,目錄當中:tests/testcases

if __name__=='__main__': 
    #使用Python執行這個模組裡面的測試用例 
    unittest.main()

測試用例收集步驟:

1)將所有待測的測試用例放在,專案目錄下new 一個directory,命名為tests / testcases裡

  2)在run_test.py中,執行收集用例的程式碼

   a). import unittest

   b).初始化一個載入器 loader = unittest.TestLoader()

   c).載入器去收集所有的測試用例(testcases裡的所有用例),放在testsuite裡面test_suite = loader.discover(case_path)

import unittest
import os

#初始化一個載入器 test_loadder
loader = unittest.TestLoader()

#獲取測試用例目錄的路徑,測試用例都放在tesetcases資料夾裡
dir_path  = os.path.dirname(os.path.abspath(__file__))
case_path = os.path.join(dir_path,'testcases')

#使用loader獲取所有的測試用例
test_suite = loader.discover(case_path)  #在case_path裡面發現所有的測試用例
print(test_suite)#就是返回一個testSuite物件,列表儲存的

執行測試用例:

  1).初始化一個執行器runner

  2).runner.run(test_suite)

import os
import unittest
#初始化一個載入器 test_loadder loader = unittest.TestLoader() #獲取測試用例目錄的路徑,測試用例都放在tesetcases資料夾裡 dir_path = os.path.dirname(os.path.abspath(__file__)) case_path = os.path.join(dir_path,'testcases') #使用loader獲取所有的測試用例 test_suite = loader.discover(case_path) #在case_path裡面發現所有的測試用例 print(test_suite)#就是返回一個testSuite物件,列表儲存的 #執行測試用例 #先初始化一個執行器runner runner = unittest.TextTestRunner() runner.run(test_suite)

五、生成測試報告

1)生成txt報告

但是在實際中,不會使用txt形式的報告,比較low,會換用HTML的報告.

import unittest
import os

#初始化一個載入器 test_loadder
loader = unittest.TestLoader()

#獲取測試用例目錄的路徑,測試用例都放在tesetcases資料夾裡
dir_path  = os.path.dirname(os.path.abspath(__file__))
case_path = os.path.join(dir_path,'testcases')

#使用loader獲取所有的測試用例
test_suite = loader.discover(case_path)  #在case_path裡面發現所有的測試用例
print(test_suite)#就是返回一個testSuite物件,列表儲存的


#執行 並生成text測試報告
with open('test_report.txt','a',encoding='utf-8') as f:
    runner  = unittest.TextTestRunner(f) #f作為引數傳入
    runner.run(test_suite)

2)生成HTML測試報告

HTML報告不是內建的,需要自己去下載HTML的測試報告的執行器和模板(HTMLTestRunnerNew.py),匯入到pycharm的seite_package 或者直接匯入專案目錄下

#執行 並生成html測試報告
with open('test_report.html','wb') as f:
    runner = HTMLTestRunner(
        f,
        title='自動化測試報告',
        description='測試報告的描述',
        tester='zjx'
    )
    runner.run(test_suite)

六、斷點除錯

1)斷點

除錯的時候使用debug模式,

打斷點 在可能出錯的地方打斷點,如果不知道哪行會出錯,就打在最開始的位置,一行一行除錯

2)打斷點如何執行?

step over:單步執行,執行到下一行

step into:執行到函式的內部

step into my code:進入自己寫的程式碼,別人寫的進不去

step out:退出函式

run to cursor:執行到指定的行

evaluate:查詢值並可對查詢到的值進行其他運算

rerun:重新執行

resume program:執行到下一個斷點

stop:停止

view breakpoints:顯示所有的斷點

mute breakpoints:關閉所有的斷點