一、UnitTest基本使用

1. UnitTest框架

1.1 什麼是框架

說明:

  1. 框架英文單詞frame
  2. 為解決一類事情的功能集合
1.2什麼是UnitTest框架

概念:UnitTest是python自帶的一個單元測試框架,用它來做單元測試

1.3為什麼使用UnitTest框架?
  1. 能夠阻止多個用例去執行
  2. 提供豐富的斷言方法
  3. 能夠生成測試報告
1.4 UnitTest框架及原理

做過自動化測試的同學應該都知道python中的unittest框架,它是python自帶的一套測試框架,學習起來也相對較容易,unittest框架最核心的四個概念:

  1. test case:就是我們的測試用例,unittest中提供了一個基本類TestCase,可以用來建立新的測試用例,一個TestCase的例項就是一個測試用例;unittest中測試用例方法都是以test開頭的,且執行順序會按照方法名的ASCII值排序。
  2. test suite:測試套件,用來把需要一起執行的測試用例集中放到一塊執行,相當於一個籃子。我們可以使用TestLoader來載入測試用例到測試套件中。
  3. test runner:用來執行測試用例的,並返回測試用例的執行結果。它還可以用圖形或者文字介面,把返回的測試結果更形象的展現出來,如:HTMLTestRunner。
  4. TestLoader:批量執行測試用例-搜尋指定資料夾內指定字母開頭的模組
  5. 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 定義測試用例
  1. 導包:import unittest
  2. 定義測試類:新建測試類必須繼承unittest.TestCase
  3. 定義測試方法:測試方法名稱命名必須為test開頭
2.3 執行測試用例

方式一:

​ 使用pycharm在程式碼上點選滑鼠右鍵,選擇使用UnitTest執行

方法二:

​ 呼叫 unittest.main() 來執行

3.TestSuite

說明:多條測試用例集合在一起就是一個TestSuite

使用:

  1. 例項化:suite = unittest.TestSuite()

    ​ (suite:為TestSuite例項化的名稱)

  2. 新增用例:suite.addTest(ClassName("MethodName"))

    ​ (ClassName:為類名;MethodName:為方法名)

  3. 新增擴充套件: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 是用來執行測試用例和測試套件的

使用:

  1. 例項化:runner = unittest.TextTestRunner()
  2. 執行:runner.run(suite) # suite: 為測試套件名稱

需求

將test01.py.....test10.py共10條用例批量執行

問題

  1. 使用suite.addtest(unittest.makeSuite(className)) 匯入10條測試類
  2. .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區別

共同點:都是測試套件;不同點:實現方式不同

  1. TestSuite需要手動新增測試用例(可以新增測試類,也可以新增測試類中的某個測試方法)
  2. TestLoader搜尋指定目錄下指定開頭.py檔案,並新增測試類中的所有的測試方法,不能指定新增測試方法

6. Fixture

需求:在一個測試類中定義多個測試方法,檢視每個測試方法執行完所花費的時間

說明: Fixture是一個概述,對一個測試用例環境的初始化和銷燬就是一個 Fixture

Fixture控制級別:

  1. 函式級別 def setUp() / def tearDown()

    ​ 特性:幾個測試函式,被執行幾次。每個測試函式執行之前都會執行setUp,執行之後都會執行tearDown

  2. 類級別 def setUpClass() / def tearDownClass()

    ​ 特性:測試類執行之前執行一次setUpClass;類執行之後執行一次tearDownClass

    ​ 注意:類方法必須使用 @classmethod裝飾

  3. 模組級別 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斷言方法

說明:

  1. Unittest中提供了非常豐富的斷言方法
  2. 複雜的斷言方法在自動化測試中幾乎使用不到,所以只需要掌握幾個常用的即可

常用的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、引數化

  1. 為什麼要引數化:

    ​ 解決冗餘程式碼問題

  2. 什麼是引數化:

    ​ 根據需求動態獲取引數並引用的過程

  3. 引數化應用場景

    ​ 解決相同業務邏輯,不同測試資料問題

通過引數的方式來傳遞資料,從而實現資料和指令碼分離。並且可以實現用例的重複執行

unittest測試框架,本身不支援引數化,但是可以通過安裝擴充套件外掛parameterized來實現

安裝

​ pip install parameterized

使用方式

  • 導包:from parameterized import parameterized

  • 修飾測試函式 @parameterized.expand([資料])

    ​ 資料格式:

    		1. 單個引數:型別為列表
    2. 多個引數:型別為列表巢狀元組
    3. 在測試函式中的引數設定變數引用引數值,注意:變數的數量必須和資料值的個數相同

9、跳過

對於一些未完成的或者不滿足測試條件的測試函式和測試類,可以跳過執行

使用方式

  1. 直接將測試函式標記成跳過

    ​ @unittest.skip('程式碼未完成')

  2. 根據條件判斷測試函式是否跳過

    ​ @unittest.skipIf(condition, reason)

10、生成HTML測試報告

操作步驟

  1. 複製HTMLTestRunner.py檔案到指定目錄

  2. 導包 from HTNLTestRunner import HTMLTestRunner

  3. 獲取報告存放檔案流,並例項化HTMLTestRunner類,執行run方法

    ​ 注意:生成HTML報告,必須使用wb,以二進位制形式寫入

with open(report_dir, "wb") as f :
HTMLTestRunner(stream=f, verbosity=2, tit le="XXX自動化測試報告", description="作業系統")