一、UnitTest基本使用
1. UnitTest框架
1.1 什麼是框架
說明:
- 框架英文單詞frame
- 為解決一類事情的功能集合
1.2什麼是UnitTest框架
概念:UnitTest是python自帶的一個單元測試框架,用它來做單元測試
1.3為什麼使用UnitTest框架?
- 能夠阻止多個用例去執行
- 提供豐富的斷言方法
- 能夠生成測試報告
1.4 UnitTest框架及原理
做過自動化測試的同學應該都知道python中的unittest框架,它是python自帶的一套測試框架,學習起來也相對較容易,unittest框架最核心的四個概念:
- test case:就是我們的測試用例,unittest中提供了一個基本類TestCase,可以用來建立新的測試用例,一個TestCase的例項就是一個測試用例;unittest中測試用例方法都是以test開頭的,且執行順序會按照方法名的ASCII值排序。
- test suite:測試套件,用來把需要一起執行的測試用例集中放到一塊執行,相當於一個籃子。我們可以使用TestLoader來載入測試用例到測試套件中。
- test runner:用來執行測試用例的,並返回測試用例的執行結果。它還可以用圖形或者文字介面,把返回的測試結果更形象的展現出來,如:HTMLTestRunner。
- TestLoader:批量執行測試用例-搜尋指定資料夾內指定字母開頭的模組
- test fixure:測試夾具,用於測試用例環境的搭建和銷燬。即用例測試前準備環境的搭建(SetUp前置條件),測試後環境的還原(TearDown後置條件),比如測試前需要登入獲取token等就是測試用例需要的環境,執行完後執行下一個用例前需要還原環境,以免影響下一條用例的測試結果。
2.TestCase
說明:TestCase就是測試用例
2.1案例
定義一個實現加法操作的函式,並對改函式進行測試
# test01.py
import unittest
def add(x,y):
return x+y
class Test01(unittest.TestCase):
def test_add(self):
result = add(1,1)
print("結果為:",result)
def test_add2(self):
result = add(1,2)
print("結果為:",result)
if __name__ == '__main__':
unittest.main()
2.2 定義測試用例
- 導包:import unittest
- 定義測試類:新建測試類必須繼承unittest.TestCase
- 定義測試方法:測試方法名稱命名必須為test開頭
2.3 執行測試用例
方式一:
使用pycharm在程式碼上點選滑鼠右鍵,選擇使用UnitTest執行
方法二:
呼叫 unittest.main() 來執行
3.TestSuite
說明:多條測試用例集合在一起就是一個TestSuite
使用:
例項化:suite = unittest.TestSuite()
(suite:為TestSuite例項化的名稱)
新增用例:suite.addTest(ClassName("MethodName"))
(ClassName:為類名;MethodName:為方法名)
新增擴充套件:suite.addTest(unittest.makeSuite(ClassName))
(搜尋指定ClassName內test開頭的方法並新增到測試套件中)
提示:TestSuite需要配合TestRunner才能被執行
#示例
import unittest
from test01 import Test01
suite = unittest.TestSuite()#例項化
suite.addTest(Test01("test_add"))# 新增一個用例
suite.addTest(unittest.makeSuite(Test01))#批量新增
# 執行
runner = unittest.TextTestRunner()
runner.run(suite)
4.TextTestRunner
說明:TextTestRunner 是用來執行測試用例和測試套件的
使用:
- 例項化:runner = unittest.TextTestRunner()
- 執行:runner.run(suite) # suite: 為測試套件名稱
需求
將test01.py.....test10.py共10條用例批量執行
問題
- 使用suite.addtest(unittest.makeSuite(className)) 匯入10條測試類
- .addtest()需要新增10次
5. TestLoader
說明:
用來載入TestCase到TestSuite中,即載入滿足條件的測試用例,並把測試用例封裝成測試套件
使用unittest.TestLoader,通過該類下面的discover()方法自動搜尋指定目錄下指定開頭的.py檔案;並將查詢到的測試用例組裝到測試套件
用法:
suite = unittest.TestLoader().discover(test_dir, pattern = 'test*.py')
自動搜尋指定目錄下指定開頭的.py檔案,並將查詢到的測試用例組裝到測試套件
test_dir:為指定的測試用例的目錄
pattern:為查詢的.py檔案的格式,預設為‘test*.py’
也可以使用unittest.defaultTestLoader 代替 unittest.TestLoader()
5.1 TestLoader與TestSuite區別
共同點:都是測試套件;不同點:實現方式不同
- TestSuite需要手動新增測試用例(可以新增測試類,也可以新增測試類中的某個測試方法)
- TestLoader搜尋指定目錄下指定開頭.py檔案,並新增測試類中的所有的測試方法,不能指定新增測試方法
6. Fixture
需求:在一個測試類中定義多個測試方法,檢視每個測試方法執行完所花費的時間
說明: Fixture是一個概述,對一個測試用例環境的初始化和銷燬就是一個 Fixture
Fixture控制級別:
函式級別 def setUp() / def tearDown()
特性:幾個測試函式,被執行幾次。每個測試函式執行之前都會執行setUp,執行之後都會執行tearDown
類級別 def setUpClass() / def tearDownClass()
特性:測試類執行之前執行一次setUpClass;類執行之後執行一次tearDownClass
注意:類方法必須使用 @classmethod裝飾
模組級別 def setUpModule() / def tearDownModule()
特性:模組執行之前執行一次 setUpModule;模組執行之後執行一次 tearDownModule
提示:
無論使用函式級別還是類幾倍,最後常用場景為:
初始化:
1. 獲取瀏覽器例項化物件
2. 最大化瀏覽器
3. 隱式等待
結束:
關閉瀏覽器驅動物件
案例:
需求:使用UnitTest框架對tpshop專案測試
1). 點選登入,進入登入頁面
2). 輸入使用者名稱和密碼,不輸入驗證碼,直接點選登入按鈕
3). 獲取錯誤提示資訊
import time
import unittest
from time import sleep
from selenium import webdriver
from parameterized import parameterized
class TestTpshopLogin(unittest.TestCase):
#初始化
def setUp(self):
# 獲取瀏覽器驅動物件
self.driver =webdriver.Chrome()
#開啟url
url ='http://www.tpshop.com'
self.driver.get(url)
#最大化
self.driver.maximize_window()
#隱式等待
self.driver.implicitly_wait(30)
def tearDown(self):
#關閉瀏覽器驅動
sleep(5)
self.driver.quit()
def test_login_code_null(self):
driver = self.driver
# 點選登入頁面
driver.find_element_by_link_text("登入").click()
# 輸入使用者名稱
driver.find_element_by_id("username").send_keys("11234567843")
# 輸入密碼
driver.find_element_by_name("password").send_keys("23615115")
# 點選登入按鈕
driver.find_element_by_name("sbtbutton").click()
# 獲取頁面錯誤資訊
result = driver.find_element_by_css_selector(".layui-layer-padding").text
print("result:",result)
expect_result ="驗證碼不能為空!!"
try:
# 斷言
self.assertEqual(expect_result,result)
except AssertionError:
# 截圖
driver.get_screenshot_as_file("./{}.png".format(time.strftime("%Y_%m_%d_%H_%M_%S")))
# 丟擲異常
raise
7. Unittest斷言
7.1 什麼是斷言
概念:讓程式代替人為判斷測試程式執行結果是否符合預期結果的過程
7.2 為什麼學習斷言
自動化監本在執行的時候一般都是無人值守狀態,我們不知道執行結果是否符合預期結果,所以我們需要讓程式代替人
為檢測程式執行的結果是否符合預期結果,就需要使用斷言
7.3 Unittest斷言方法
說明:
- Unittest中提供了非常豐富的斷言方法
- 複雜的斷言方法在自動化測試中幾乎使用不到,所以只需要掌握幾個常用的即可
常用的Unittest斷言方法
序號 斷言方法 斷言描述 1 assertTrue(rxpr, msg=None) 驗證expr是true,如果為false,則fail 2 assertFalse(expr, msg=None) 驗證expr是false如果為true,則fail 3 assertEqual(expected, actual, msg=None) 驗證expected == actual,不等則fail 4 assertNotEqual(first, second, msg=None) 驗證first != second,相等則fail 5 assertIsNone(obj, msg=None) 驗證obj是None,不是則fail 6 assertIsNotNone(obj, msg=None) 驗證obj不是是None,是則fail 7 assertIn(member, container, msg=None) 驗證是否member in container 8 assertNotIn(member, container, msg=None) 驗證是否member not in container
如果斷言失敗即不通過就會丟擲一個AssertionError斷言錯誤,成功則標識為通過,以上幾種方式都有一個共同點,就是都有一個msg引數,預設是None,即msg = None,如果指定msg引數的值,則將該資訊作為失敗的錯誤資訊返回。
8、引數化
為什麼要引數化:
解決冗餘程式碼問題
什麼是引數化:
根據需求動態獲取引數並引用的過程
引數化應用場景
解決相同業務邏輯,不同測試資料問題
通過引數的方式來傳遞資料,從而實現資料和指令碼分離。並且可以實現用例的重複執行
unittest測試框架,本身不支援引數化,但是可以通過安裝擴充套件外掛parameterized來實現
安裝
pip install parameterized
使用方式
導包:from parameterized import parameterized
修飾測試函式 @parameterized.expand([資料])
資料格式:
1. 單個引數:型別為列表
2. 多個引數:型別為列表巢狀元組
3. 在測試函式中的引數設定變數引用引數值,注意:變數的數量必須和資料值的個數相同
9、跳過
對於一些未完成的或者不滿足測試條件的測試函式和測試類,可以跳過執行
使用方式
直接將測試函式標記成跳過
@unittest.skip('程式碼未完成')
根據條件判斷測試函式是否跳過
@unittest.skipIf(condition, reason)
10、生成HTML測試報告
操作步驟
複製HTMLTestRunner.py檔案到指定目錄
導包 from HTNLTestRunner import HTMLTestRunner
獲取報告存放檔案流,並例項化HTMLTestRunner類,執行run方法
注意:生成HTML報告,必須使用wb,以二進位制形式寫入
with open(report_dir, "wb") as f :
HTMLTestRunner(stream=f, verbosity=2, tit le="XXX自動化測試報告", description="作業系統")