一、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="操作系統")