一、單元測試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:關閉所有的斷點