1. 程式人生 > 實用技巧 >自動化測試-高階篇

自動化測試-高階篇

目標

為什麼使用UnitTest框架? 1. 能組織用例和執行用例 2. 提供豐富的斷言方法 3. 提供豐富的日誌與測試結果

單元測試框架

掌握UnitTest框架的基礎使用方法什麼是框架說明: 1. 框架英文單詞FrameWork; 2. 為解決一類事情的功能集合;什麼是UnitTest框架概念:UnitTest框架是專門用來進行執行程式碼測試的框架;為什麼使用UnitTest框架1. 能夠組織多個用例去執行2. 提供豐富的斷言方法3. 提供豐富的日誌與測試結果提示在學習UnitTest框架之前,我們先了解下UnitTest框架內幾個核心要素UnitTest核心要素
1. TestCase
2. TestSuite
3. TextTestRunner
4. Fixture

TestCase(測試用例)

說明:(翻譯:測試用例)一個TestCase就是一條測試用例;
使用:
    1. 導包:import unittest             --> 匯入unitest框架
    2. 繼承:unittest.TestCase             --> 新建測試類繼承unittest.TestCase

提示:
    1). 測試用例:在自動化測試中,一條用例就是一個完整的測試流程;                
    2). 測試方法名稱命名必須以test開頭;
       (原因:unittest.TestCase類批量執行的方法是搜尋執行test開頭的方法)
Python
L1 (default)
已複製
# 匯入unittest
import  unittest
class Test01(unittest.TestCase): # 新建測試類繼承unittest.TestCase
    # 測試方法名稱必須以test開頭
    def test001(self):
        print('test001被執行')
    def test002(self):
        print('test002被執行')

if __name__ == '__main__': # 可以看看python當中的__name__,當前檔案執行,__name__==main
    unittest.main() # 執行以test開頭的方法
'''
    結果:
    Test01-->test001被執行
    Test01-->test002被執行
'''

TestSuite

說明:(翻譯:測試套件)多條測試用例集合在一起,就是一個TestSuite;
使用:
    1. 例項化:     suite=unittest.TestSuite()                    
                 (suite:為TestSuite例項化的名稱)
    2. 新增用例:suite.addTest(ClassName("MethodName"))    
                 (ClassName:為類名;MethodName:為方法名)

    3. 新增擴充套件:suite.addTest(unittest.makeSuite(ClassName))
                 (搜尋指定ClassName內test開頭的方法並新增到測試套件中)

提示:
    1). 一條測試用例(.py)內,多個方法也可以使用測試套件
    2). TestSuite需要配合TextTestRunner才能被執行

# 匯入unittest
import unittest
# 匯入測試用例.py
from TestCase.Test01 import Test01
from TestCase.Test02 import Test02
from TestCase.Test03 import Test03
if __name__ == '__main__':
    # 例項化suite
    suite=unittest.TestSuite()
    # 呼叫 新增用例方法 className(methonName)
    suite.addTest(Test01('test001'))
    suite.addTest(Test02('test002'))
    suite.addTest(Test03('test003'))
    # 執行testsuite
    unittest.TextTestRunner().run(suite)
'''
結果:
    Test01-->test001被執行
    Test02-->test002被執行
    Test03-->test003被執行
'''

# 匯入unittest
import unittest
# 匯入測試用例.py
from TestCase.Test01 import Test01
from TestCase.Test02 import Test02
from TestCase.Test03 import Test03
if __name__ == '__main__':
    # 例項化suite
    suite=unittest.TestSuite()
    # 呼叫 新增用例方法 ClassName
    # 搜尋指定ClassName內test開頭的方法並新增到測試套件中
    suite.addTest(unittest.makeSuite(Test02))
    # 執行testsuite
    unittest.TextTestRunner().run(suite)
'''
結果:
    Test02-->test001被執行
    Test02-->test002被執行
    Test02-->test003被執行
'''

# 匯入unittest
import unittest
# 匯入測試用例.py
from TestCase.Test01 import Test01
from TestCase.Test02 import Test02
from TestCase.Test03 import Test03
if __name__ == '__main__':
    # 搜尋指定目錄指定的py檔案,並返回所有搜尋檔案內test開頭的方法,以測試套件的形式返回
    # 定義測試套件
    suite=unittest.defaultTestLoader.discover('.',pattern='Test*.py')
    unittest.TextTestRunner().run(suite)

TextTestRunner

說明:(翻譯:以文字形式執行測試)是用來執行測試用例套件
使用:
    1. 例項化: runner=unittest.TextTestRunner()
                (runner:TextTestRunner例項化名稱)
    2. 執行:    runner.run(suite)
                (suite:為測試套件名稱)

Fixture

說明:是一個概述,對一個測試用例環境的搭建和銷燬就是一個Fixture;
使用:
    1. 初始化(搭建):def setUp(self)        --> 首先執行
       (setUp:此方法繼承於unittest.TestCase)        
    2. 結束(銷燬):    def tearDown(self)        --> 最後執行
       (tearDown:此方法繼承於unittest.TestCase)
提示:
    1. 必須繼承unittest.TestCase類,setUp、tearDown才是一個Fixture;
    2. setUp:一般做初始化工作,比如:例項化瀏覽器、瀏覽器最大化、隱式等待設定
    3. tearDown:一般做結束工作,比如:退出登入、關閉瀏覽器
    4. 如果一個測試類有多個test開頭方法,則每個方法執行之前都會執行setUp、結束時執行tearDown

案例

需求:使用UnitTest框架對iweb_shop專案測試 1. 登陸進行測試操作步驟分析:
1. 導包 import unittest
2. 新建測試類並繼承unittest.TestCase
3. 新建一個Fixture(setUp、tearDown)
4. 新建登入方法
5. if __name__ == '__main__':
6. unittest.main()執行

程式碼實現:

import unittest
from time import sleep
from selenium import webdriver
class TestLoginOut(unittest.TestCase):
    def setUp(self):
        # self.driver 是成員屬性,被類物件內部共享
        # self指代當前物件
        # driver 是區域性變數,生命週期在當前方法內
        # 這裡由於driver物件在後面還用到也就是要共享,所以將其設為物件內部屬性,呼叫時self.driver
        self.driver = webdriver.Firefox()
        url = 'http://localhost/iwebshop/'
        self.driver.get(url)
        # 設定隱式等待10s
        self.driver.implicitly_wait(10)
        # 最大化瀏覽器物件
        self.driver.maximize_window()
        print('setup')
    def test_login(self):
        driver = self.driver
        driver.find_element_by_link_text('登入').click()
        driver.find_element_by_css_selector('input[alt*="郵箱"]').send_keys('admin')
        driver.find_element_by_css_selector('input[alt*="密碼"]').send_keys('123456')
        driver.find_element_by_css_selector('.submit_login').click()
        sleep(3)
        driver.find_element_by_css_selector('.reg').click()
    def tearDown(self):
        sleep(2)
        self.driver.quit() # 確保是同一個瀏覽器物件
        print('tearDown')
    if __name__=='main':
        # 呼叫main方法執行unittest內所有test開頭方法
        unittest.main()

回顧

為什麼使用UnitTest框架? 1. 能組織用例和執行用例 2. 提供豐富的斷言方法 3. 提供豐富的日誌與測試結果1. UnitTest用例組織和執行用例方法我們基本就學完了2. 接下來我們學習UnitTest框架的斷言方法

UnitTest斷言

什麼是斷言?

概念:讓程式代替人為判斷測試程式執行結果是否符合預期結果的過程

為什麼要學習斷言?

自動化指令碼在執行的時候一般都是無人值守狀態,我們不知道執行結果是否符合預期結果,
所以我們需要讓程式代替人為檢測程式執行的結果是否符合預期結果,這就需要使用斷言;

UnitTest斷言分類

1. 基本布林型斷言
2. 比較斷言
3. 複雜斷言

提示:
    1. 這裡這介紹基本布林型別斷言 說明:結果只有True和False
    2. 比較斷言、複雜斷言有興趣的同學請參考4.4附件資料

案例

需求:
    1. iweb專案登陸,輸入正確使用者名稱和密碼,斷言登入成功的使用者名稱是否為admin,如果斷言失敗截圖儲存
擴充套件:
    1. 圖片名稱為動態-時間
    2. 圖片名稱新增斷言錯誤資訊

實現步驟分析

1. 成功登陸
2. 獲取登陸後的資訊
3. 新增斷言

斷言主要程式碼實現

 # 獲取登陸資訊,因為沒有開啟新視窗,所以控制代碼沒變化,還是在當前視窗查詢元素
import sys
import time
import unittest
from time import sleep
from selenium import webdriver
class TestLoginOut(unittest.TestCase):
    def setUp(self):
        # self.driver 是成員屬性,被類物件內部共享
        # self指代當前物件
        # driver 是區域性變數,生命週期在當前方法內
        self.driver = webdriver.Firefox()
        url = 'http://localhost/iwebshop/'
        self.driver.get(url)
        # 設定隱式等待10s
        self.driver.implicitly_wait(10)
        # 最大化瀏覽器物件
        self.driver.maximize_window()
        print('setup')
    def test_login(self):
        driver = self.driver
        driver.find_element_by_link_text('登入').click()
        driver.find_element_by_css_selector('input[alt*="郵箱"]').send_keys('admin')
        driver.find_element_by_css_selector('input[alt*="密碼"]').send_keys('123456')
        driver.find_element_by_css_selector('.submit_login').click()
        # 獲取登入後的提示資訊
        text = driver.find_element_by_css_selector('.loginfo').text
        try:
            self.assrtIn('admin',text)
        except AssertionError:
            # 設定時間字串(獲取執行時系統時間)
            nowtime = time.strftime('%Y_%m_%d %H_%M_%S')
            # 擷取螢幕
            driver.get_screenshot_as_file('../Image/%s---%s.jpg' % nowtime,sys.exc_info()[1])
            # 丟擲捕獲的異常,並終止後面的程式碼
            raise AssertionError
        # 退出
        sleep(3)
        driver.find_element_by_link_text('安全退出').click()
    def tearDown(self):
        sleep(2)
        self.driver.quit() # 確保是同一個瀏覽器物件
        print('tearDown')
    if __name__=='main':
        # 呼叫main方法執行unittest內所有test開頭方法
        unittest.main()

測試結果-HTML測試報告

什麼是HTML測試報告

說明:HTML測試報告就是執行完測試用例後以HTML(網頁)方式將執行結果生成報告

為什麼要生成測試報告

1. 測試報告是本次測試目的最終體現形態
2. 測試報告內包含了有關本次測試用例的詳情

HTML生成報告方式

Export Test Results (自帶)



    提示:適合單條用例執行時使用

HTMLTestRunner【重點】


測試報告 生成步驟分析
1. 複製HTMLTestRunner.py檔案到專案資料夾
2. 匯入HTMLTestRunner、UnitTest包    
3. discover載入要執行的用例
      (discover=unittest.defaultTestLoader.discover(test_dir,pattern="test*.py"))
4. 設定報告生成路徑和檔名
   (file_name=file_dir+nowtime+"Report.html")
 5. 開啟報告 with open(file_name,'wb') as f:  # 沒有會自動生成檔案
 6. 例項化HTMLTestRunner物件:runner=HTMLTestRunner(stream=f,[title],[description])
 引數說明:
               (stream:檔案流,開啟寫入報告的名稱及寫入編碼格式)
               (
                       [],為可選;
                       title為報告標題,如XXX自動化測試報告
                       description:為說明;比如作業系統、瀏覽器等版本
               )
7. 執行:runner.run(discover)

實現程式碼

# 匯入unittest
import time
import unittest
# 匯入HTMLTestRunner.py
import TestCase.HTMLTestRunner
# 匯入測試用例.py
from TestCase.HTMLTestRunner import HTMLTestRunner
from TestCase.Test01 import Test01
from TestCase.Test02 import Test02
from TestCase.Test03 import Test03
test_dir='.'

if __name__ == '__main__':
    # 載入當前目錄下test開頭的.py檔案
    discover = unittest.defaultTestLoader.discover(test_dir, pattern="Test*.py")
    # 定義報告目錄
    file_dir = '../Report/'
    # 定義報告名稱格式
    nowtime=time.strftime("%Y-%m-%d %H_%M_%S")
    # 報告完整路徑和名稱
    file_name = file_dir+nowtime+'Report.html'
    with open(file_name,'wb') as f: # 二進位制形式寫入
        # 例項化HTMLTestRunner 物件,傳入報告檔案流f
        runner = HTMLTestRunner(stream=f,title='web自動化測試報告',description='孫騰寫的')
        runner.run(discover)