selenium - 用例執行失敗后自動截圖(裝飾器)


循序漸進的方式介紹(也可以直接到步驟4中看示例模板)

 

1. 簡單示例:

from selenium import webdriver
import time
driver = webdriver.Chrome()


def get_screen():
    now_time = time.strftime('%Y_%m_%d_%H_%M_%S')
    driver.get_screenshot_as_file(f'{now_time}.jpg')


def screen(func):   # 自動截圖裝飾器
    def inner(*args, **kwargs):  # 由於我們不知道被調用的函數到底有幾個參數,寫一個萬能裝飾器,傳可變參數
        try:
            f = func(*args, **kwargs)
            # return f
        except:
            get_screen()   # 失敗后截圖
            # raise
    return inner


@screen   # 加裝飾
def search(driver):
    driver.get('http://www.baidu.com')
    driver.find_element_by_id('kw11').send_keys('python')  # id不對,會運行失敗
    driver.find_element_by_id('su').click()
    time.sleep(5)
    driver.quit()


search(driver)  # 執行

以上代碼,會發現driver作為全局變量存在,無法傳入裝飾器中。同時,也沒有和unittest結合。我們對此進行改良。 

 

2. 不帶參數的裝飾器

  • 被裝飾的函數,傳入__init__()
  • 調用被裝飾的函數時,自動調用__call__()

__init__()里是初始化參數,__call__()里是原函數參數

class decoratorWithoutArguments(object):
    def __init__(self, f):    # 被裝飾的函數,傳入__init__()
        print('inside __init__()')
        self.f = f

    def __call__(self, *args):   # 調用被裝飾的函數時,自動調用__call__()
        print('inside __call__()')
        self.f(*args)
        print('after self.f(*args)')


@decoratorWithoutArguments  # 不帶參數
def say_hello(a1, a2):
    print('say hello arguments: ', a1, a2)


say_hello(2, 3)

運行結果如下:

inside __init__()
inside __call__()
say hello arguments: 2 3
after self.f(*args)

 

3. 帶參數的裝飾器

  • 參數寫到__init()__里
  • 被裝飾的函數傳入__call()__
class decoratorWithArguments(object):
    def __init__(self, arg1, arg2, arg3):  # 傳入裝飾器參數
        print('inside __init__()')
        self.arg1 = arg1
        self.arg2 = arg2
        self.arg3 = arg3

    def __call__(self, f):   # 可以只給它傳一個參數 -- 被裝飾的函數
        print('inside __call__()')
        
        def wrapped_f(*args):
            print('inside wrapped_f()')
            print('decorator arguments: ', self.arg1, self.arg2, self.arg3)
            f(*args)
            print('after f(*args)')
        return wrapped_f


@decoratorWithArguments('hello', 'world', 42)  # 帶參數
def say_hello(a1, a2, a3, a4):
    print('say_hell0 arguments: ', a1, a2, a3, a4)


say_hello(1, 2, 3, 4)

運行結果如下:

inside __init__()
inside __call__()
inside wrapped_f()
decorator arguments: hello world 42
say_hell0 arguments: 1 2 3 4
after f(*args)

 

so,可以嘗試按此方法,將瀏覽器驅動傳入裝飾器中

 

4. 結合unittest

 百度首頁為例,有異常時截圖,代碼如下:

from selenium import webdriver
import unittest
import time


class Screen(object):
    def __init__(self, driver):
        self.driver = driver

    def __call__(self, func):
        def inner(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except:
                now_time = time.strftime('%Y_%m_%d_%H_%M_%S')   # 異常時,截圖
                self.driver.get_screenshot_as_file(f'{now_time}.png')
                raise   # 拋出異常,不然會認為測試用例執行通過
        return inner


class MyTest(unittest.TestCase):
    driver = webdriver.Chrome()

    @classmethod
    def setUpClass(cls):
        cls.driver.get('http://www.baidu.com')

    @Screen(driver)
    def test_01(self):
        self.driver.find_element_by_id('kw').clear()
        self.driver.find_element_by_id('kw').send_keys('python')
        self.driver.find_element_by_id('su1').click()  # id不對,會報錯
        time.sleep(3)

    @Screen(driver)
    def test_02(self):
        self.driver.find_element_by_id('kw').clear()
        self.driver.find_element_by_id('kw').send_keys('selenium')
        self.driver.find_element_by_id('su').click()
        time.sleep(3)

    @classmethod
    def tearDownClass(cls):
        cls.driver.quit()


if __name__ == '__main__':
    unittest.main()

截圖如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM