1. 程式人生 > 實用技巧 >python測試系列教程——python+Selenium+chrome自動化測試框架

python測試系列教程——python+Selenium+chrome自動化測試框架

當我們以指令碼的形式編寫了大量的自動化測試程式碼後,很容易發現程式碼可讀性太差了、任何一個測試指令碼幾乎毫無擴充套件能力或者說擴充套件起來只能修改邊邊角角、一旦被測系統的UI層發生變化對於測試程式碼的修改來說簡直就是災難性的,整個自動化工程幾乎毫無結構可言,當面臨這些問題的時候實際上已經失去了一部分自動化測試原有的職能

任何自動化測試團隊在開展自動化測試這項活動的之前,必須考慮的是這項活動的ROI,自動化測試的本職是解放人力,基於前邊所述的常見情況不僅僅其ROI非常低,也違背了自動化的初衷

基於這個大背景下,常規的自動化測試活動必須引入PO模式,它是一種自動化測試的設計模式,也是一種解耦的思想即:以頁面為單位,將頁面中的控制元件及控制元件的動作逐一提煉,從而在測試指令碼中可以直接使用,其最終目的是使得元素定位表示式``頁面物件``測試程式碼

三者分離

而分離後的測試程式碼,具有極高的可複用性、可讀性,可維護性,可擴充套件性,而這像極了面向物件思想更像極了Java裡Spring的MVC模式和Django的MTV模式

定義基本頁面類

在自動化測試活動中,每個頁面都有其獨特的地方,每個月面有都與其共性,為了達到PO模式的目的,首先需要考慮的是每個月面的共性,第一項需要做的就是定義頁面的基本特性及活動,它是所有頁面類的基類,是獨立於所有實際頁面之外的

例項程式碼

# encoding = utf-8
from selenium import webdriver
from selenium.webdriver.common.by import By
from time import sleep


class Page():
    """
    基礎類,僅用於定義一些頁面常規內容及方法
    後續各個頁面類繼承該類實現各自頁面的特別內容及方法
    """
    login_url = 'http://mail.163.com'  # 定義基類引數預設值,當呼叫時未提供該引數時使用

    def __init__(self, driver, base_url=login_url):
        self.base_url = base_url
        self.driver = driver
        self.timeout = 30

    def target_page(self):
        return self.driver.current_url == self.base_url  #  判斷當前開啟的url與引數給的url是否一致

    def open(self, url):
    	"""開啟頁面"""
        url = self.base_url
        self.driver.get(url)
        print(self.driver.current_url)
        
    def find_element(self, *loc):
        return self.driver.find_element(*loc)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

定義具體頁面類

定義了基本頁面類,接下來便是具體到每個頁面,因為每個也面都有不同,定義具體頁面類也是定義其不同,但凡有相同的都應該抽象到基本頁面類中去定義

class LoginPage(Page):
    """
    登陸頁面,頁面物件類
    """
    url = '/'
    """
    此處我們暫時稱頁面元素為物件,雖然本程式碼並非那麼像物件,後續的框架中我們更高度的封裝它便是個可操作的物件
    """
    username_loc = (By.NAME, "email")  # 頁面控制元件物件:輸入使用者名稱的input控制元件
    password_loc = (By.NAME, "password")  # 頁面控制元件物件:輸入密碼的input控制元件
    submit_loc = (By.ID, "dologin")  # 頁面控制元件物件:登陸按鈕的button控制元件

    """
    為每個頁面元素物件封裝其相對應的方法
    """
    def input_username(self, username):
        self.find_element(*self.username_loc).send_keys(username)  # 輸入使用者名稱

    def input_password(self, password):
        self.find_element(*self.password_loc).send_keys(password)  # 輸入密碼

    def click_submitbutton(self):
        self.find_element(*self.submit_loc).click()  # 點選登陸按鈕


def user_login(driver, username, password):
    login_page = LoginPage(driver)
    login_page.open()
    sleep(5)
    driver.switch_to.frame(driver.find_element_by_xpath("//*[@id='loginDiv']/iframe"))
    login_page.input_username(username)
    sleep(3)
    login_page.input_password(password)
    sleep(3)
    login_page.click_submitbutton()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

編寫測試指令碼

定義基本頁面類是為了更快速的定義具體頁面類,使得頁面物件的共性可以複用,減少測試程式碼量;定義具體頁面類實際上是擴充套件了基本頁面類,相對於基本頁面類而言它是獨特的頁面類;之後,便可以輕鬆的編寫自動化測試指令碼,指令碼內容也變得簡潔而清晰

def login_main163():
    try:
        driver = webdriver.Chrome()
        username = 'xxxxxx'  # 登陸郵箱需要的真實賬號
        password = 'xxxxxx'  # 登陸郵箱需要的真實密碼
        user_login(driver, username, password)  # 呼叫前面封裝好的user_login方法
        sleep(3)  #  等待3秒
        driver.switch_to.default_content()  # 切換出iframe
        assert_string = driver.find_element_by_xpath("/html/body/div[1]/nav/div[1]/ul/li[1]/span[2]").text
        print(assert_string)
        assert (assert_string == '收 信')  # 斷言關鍵字
    finally:
        driver.quit()  # 關閉瀏覽器視窗


if __name__ == '__main__':
    main()