亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

python基于Selenium的web自動(dòng)化框架

 更新時(shí)間:2019年07月14日 10:17:55   作者:Alvin_Xu  
這篇文章主要介紹了python基于Selenium的web自動(dòng)化框架,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1 什么是selenium

Selenium 是一個(gè)基于瀏覽器的自動(dòng)化工具,它提供了一種跨平臺(tái)、跨瀏覽器的端到端的web自動(dòng)化解決方案。Selenium主要包括三部分:Selenium IDE、Selenium WebDriver 和Selenium Grid:

  • Selenium IDE:Firefox的一個(gè)擴(kuò)展,它可以進(jìn)行錄制回放,并可以把錄制的操作以多種語(yǔ)言(例如java,python等)的形式導(dǎo)出成測(cè)試用例。
  • Selenium WebDriver:提供Web自動(dòng)化所需的API,主要用作瀏覽器控制、頁(yè)面元素選擇和調(diào)試。不同的瀏覽器需要不同的WebDriver。
  • Selenium Grid:提供了在不同機(jī)器的不同瀏覽器上運(yùn)行selenium測(cè)試的能力

本文中主要使用python結(jié)合Selenium WebDriver庫(kù)進(jìn)行自動(dòng)化測(cè)試框架的搭建。

2 自動(dòng)化測(cè)試框架

一個(gè)典型的自動(dòng)化測(cè)試框架一般包括用例管理模塊、自動(dòng)化執(zhí)行控制器、報(bào)表生成模塊和日志模塊等,這些模塊之間不是相互孤立的,而是相輔相成的。

下面來(lái)介紹下每個(gè)模塊的邏輯單元:

  • 用例管理模塊

用例管理模塊包括用例的添加、修改、刪除等操作單元,這些單元也會(huì)涉及到用例書寫的模式,測(cè)試數(shù)據(jù)的管理、可復(fù)用庫(kù)等

  • 自動(dòng)化執(zhí)行控制器

控制器是自動(dòng)化用例執(zhí)行的組織模塊,主要負(fù)責(zé)以什么方式去執(zhí)行用例。比較典型的控制器有用戶圖形界面(GUI)和“commandline+文件”兩種。

  • 報(bào)表生成模塊

報(bào)表生成模塊主要負(fù)責(zé)執(zhí)行完用例以后生成報(bào)表,報(bào)表一般以HTML格式居多,信息主要包括用例的執(zhí)行情況及相應(yīng)的總結(jié)報(bào)告。另外還可以添加發(fā)送郵件功能。

  • 日志模塊

日志模塊主要用來(lái)記錄用例的執(zhí)行情況,以便于更高效的調(diào)查用例失敗信息及追蹤用例執(zhí)行情況。

3 自動(dòng)化框架的設(shè)計(jì)與實(shí)現(xiàn)

3.1 需求分析

測(cè)試對(duì)象是一個(gè)典型的后臺(tái)系統(tǒng)的Web展現(xiàn)平臺(tái),基于此平臺(tái)設(shè)計(jì)的自動(dòng)化框架要包含測(cè)試用例管理、測(cè)試執(zhí)行控制、測(cè)試報(bào)表及測(cè)試日志的生成,整體測(cè)試框架要輕量易用。

3.2 概要設(shè)計(jì)

概要設(shè)計(jì)包括了四個(gè)大的模塊:公共庫(kù)模塊(可復(fù)用函數(shù)、日志管理、報(bào)表管理以及發(fā)送郵件管理)、用例倉(cāng)庫(kù)(具體用例的管理)、頁(yè)面管理(單獨(dú)對(duì)Web頁(yè)面進(jìn)行抽象,封裝頁(yè)面元素和操作方法)以及執(zhí)行模塊。

概要設(shè)計(jì)類圖:

3.3 詳細(xì)設(shè)計(jì)與實(shí)現(xiàn)

3.3.1 頁(yè)面管理

測(cè)試Web對(duì)象是一個(gè)典型的單頁(yè)面應(yīng)用,因此采用頁(yè)面模式(page pattern)來(lái)進(jìn)行組織:

頁(yè)面模式是頁(yè)面與測(cè)試用例之間的橋梁,它將每個(gè)頁(yè)面抽象成一個(gè)單獨(dú)的頁(yè)面類,為測(cè)試用例提供頁(yè)面元素的定位和操作。

頁(yè)面模式的類圖如下:

BasePage作為基類只包含一個(gè)driver成員變量,它用來(lái)標(biāo)記Selenium中的WebDriver,以便在BasePage的派生類中定位頁(yè)面元素。LoginPage和PageN等作為派生類,可以提供相應(yīng)頁(yè)面元素的定位和操作方法。比如測(cè)試對(duì)象的登錄頁(yè)面:

從頁(yè)面可以看出,需要操作的頁(yè)面元素分別為:Username,Password,remember my username checkbox和Sign in按鈕,它們對(duì)應(yīng)的操作為輸入用戶名和密碼,點(diǎn)選checkbox和點(diǎn)擊Sign In按鈕,具體代碼級(jí)別的實(shí)現(xiàn)如下:

頁(yè)面基類BasePage.py:

class BasePage(object): 
  """description of class""" 
 
  #webdriver instance 
  def __init__(self, driver): 
    self.driver = driver 

LoginPage頁(yè)面繼承自BasePage,并進(jìn)行Login Page的元素定位及操作實(shí)現(xiàn)。代碼中定位了username和password,并且添加了設(shè)置用戶名和密碼的操作。

from BasePage import BasePage 
from selenium.webdriver.common.by import By 
from selenium.webdriver.common.keys import Keys 
 
class LoginPage(BasePage): 
  """description of class""" 
   #page element identifier 
  usename = (By.ID,'username') 
  password = (By.ID, 'password') 
  dialogTitle = (By.XPATH,"http://h3[@class=\"modal-title ng-binding\"]") 
  cancelButton = (By.XPATH,'//button[@class=\"btn btn-warning ng-binding\"][@ng-click=\"cancel()\"]') 
  okButton = (By.XPATH,'//button[@class=\"btn btn-primary ng-binding\"][@ng-click=\"ok()\"]') 
 
  #Get username textbox and input username 
  def set_username(self,username): 
    name = self.driver.find_element(*LoginPage.usename) 
    name.send_keys(username) 
   
  #Get password textbox and input password, then hit return 
  def set_password(self, password): 
    pwd = self.driver.find_element(*LoginPage.password) 
    pwd.send_keys(password + Keys.RETURN) 
 
  #Get pop up dialog title 
  def get_DiaglogTitle(self): 
    digTitle = self.driver.find_element(*LoginPage.dialogTitle) 
    return digTitle.text 
 
  #Get "cancel" button and then click 
  def click_cancel(self): 
    cancelbtn = self.driver.find_element(*LoginPage.cancelButton) 
    cancelbtn.click() 
 
   #click Sign in 
  def click_SignIn(self): 
    okbtn = self.driver.find_element(*LoginPage.okButton) 
    okbtn.click()

采用頁(yè)面模式來(lái)管理頁(yè)面和測(cè)試用例有很多好處,主要體現(xiàn)在:

  • 簡(jiǎn)單并且清晰

每個(gè)頁(yè)面都有單獨(dú)的類來(lái)封裝頁(yè)面元素和操作,讓頁(yè)面操作更加具體化,而不是相對(duì)獨(dú)立的。

比如未使用頁(yè)面模式,測(cè)試用例的輸入用戶名和密碼的代碼:

 #enter username and password 
driver.find_element_by_id("username").clear() 
driver.find_element_by_id("username").send_keys("sbxadmin") 
driver.find_element_by_id("password").clear() 
driver.find_element_by_id("password").send_keys("password"+Keys.RETURN) 

使用頁(yè)面模式之后,輸入用戶名和密碼的代碼:

#Step2: Open Login page 
login_page = BasePage.LoginPage(self.driver) 
#Step3: Enter username 
login_page.set_username("username") 
#Step4: Enter password 
login_page.set_password("password") 

通過(guò)對(duì)比我們不難發(fā)現(xiàn),未使用頁(yè)面模式的代碼組織比較混亂,步驟多,可讀性非常差,不難想象,一個(gè)通篇都是find_element_by_id或者send_Keys的測(cè)試用例到底有多糟糕!而使用了頁(yè)面模式之后,在哪個(gè)頁(yè)面做什么操作都非常清晰,非常接近測(cè)試用例的步驟,易讀性非常好。

  • 可復(fù)用性好

由于頁(yè)面操作都被封裝在了頁(yè)面類中,所以頁(yè)面方法和容易調(diào)用,可復(fù)用性非常好。而未使用頁(yè)面模式的用例只能每次都實(shí)現(xiàn)一遍。

  • 可維護(hù)性好

由于測(cè)試目標(biāo)頁(yè)面的多變性,頁(yè)面元素的定位經(jīng)常需要改變,利用了頁(yè)面模式后,只需要修改一遍其頁(yè)面類中的定位就可以對(duì)所用用到該元素的測(cè)試用例生效;而在未使用該模式的情況下,必須修改每一個(gè)用到該元素的測(cè)試用例,非常容易遺漏,工作量也非常大。

綜合以上頁(yè)面模式的各種優(yōu)點(diǎn),我們?cè)谝院蟮膚eb自動(dòng)化中可以多使用該模式來(lái)組織頁(yè)面。

3.3.2 公共庫(kù)模塊

公共庫(kù)模塊是為創(chuàng)建測(cè)試用例服務(wù)的,它主要包括常量、公共函數(shù)、日志管理、報(bào)表管理以及發(fā)送郵件管理等。

公共庫(kù)模塊涉及到的功能一般多而雜,在設(shè)計(jì)的時(shí)候只要遵循高內(nèi)聚低耦合就可以了。比如常量、變量和一些公共函數(shù)可以放在同一個(gè)文件中Common.py:

from datetime import datetime 
 
def driverPath(): 
  return r'C:\Users\xua\Downloads\chromedriver_win32\chromedriver.exe' 
def baseUrl(): 
  return "https://xxx.xxx.xxx.xxx:9000" 
#change time to str 
def getCurrentTime(): 
  format = "%a %b %d %H:%M:%S %Y" 
  return datetime.now().strftime(format) 
# Get time diff 
def timeDiff(starttime,endtime): 
  format = "%a %b %d %H:%M:%S %Y" 
  return datetime.strptime(endtime,format) - datetime.strptime(starttime,format)

測(cè)試用例信息類用來(lái)標(biāo)識(shí)測(cè)試用例,并且包括執(zhí)行用例執(zhí)行結(jié)果信息,主要包括以下字段:

class TestCaseInfo(object): 
  """description of class""" 
  def __init__(self, id="",name="",owner="",result="Failed",starttime="",endtime="",secondsDuration="",errorinfo=""): 
    self.id = id 
    self.name = name 
    self.owner = owner 
    self.result = result 
    self.starttime = starttime 
    self.endtime = endtime 
 self.secondsDuration = secondsDuration 
 self.errorinfo = errorinfo

測(cè)試用例信息需要在每個(gè)測(cè)試用例中實(shí)例化,以便對(duì)測(cè)試用例進(jìn)行標(biāo)記,并最終體現(xiàn)在測(cè)試報(bào)告中。

日志主要用來(lái)記錄測(cè)試用例執(zhí)行步驟及產(chǎn)生的錯(cuò)誤信息,不同的信息有不同的日志級(jí)別,比如Information,Warning,Critical和Debug。由于每個(gè)測(cè)試用例產(chǎn)生的日志條目比較少,所以在測(cè)試框架中只利用了最高級(jí)別的日志打印,即Debug級(jí)別,該級(jí)別也會(huì)將其他所有的日志級(jí)別的信息同樣打印出來(lái)。在具體的實(shí)現(xiàn)中引用了Python標(biāo)準(zhǔn)庫(kù)中的logging類庫(kù),以便更方便的控制日志輸出:

import logging 
import ResultFolder 
 
logger = logging.getLogger() 
logger.setLevel(logging.DEBUG) 
 
 
def CreateLoggerFile(filename): 
  try: 
    fulllogname = ResultFolder.GetRunDirectory()+"\\"+filename+".log" 
    fh = logging.FileHandler(fulllogname) 
    fh.setLevel(logging.DEBUG) 
    formatter = logging.Formatter('%(asctime)s [line:%(lineno)d] %(message)s') 
    fh.setFormatter(formatter) 
    logger.addHandler(fh) 
  except Exception as err: 
    logger.debug("Error when creating log file, error message: {}".format(str(err))) 
 
 
def Log(message): 
  logger.debug(message)

報(bào)表管理及發(fā)送郵件模塊實(shí)現(xiàn)了報(bào)表(html格式)的生成及自動(dòng)發(fā)送郵件的功能。報(bào)表和郵件依附于當(dāng)前測(cè)試的執(zhí)行,每次執(zhí)行都會(huì)獨(dú)立的觸發(fā)報(bào)表生成和郵件發(fā)送。該模塊主要運(yùn)用了Python中的lxml、smtplib和email庫(kù)。

3.3.3 用例倉(cāng)庫(kù)

用例倉(cāng)庫(kù)主要用來(lái)組織自動(dòng)化測(cè)試用例。每條測(cè)試用例都被抽象成一個(gè)獨(dú)立的類,并且均繼承自u(píng)nittest.TestCase類。 Python中的unittest庫(kù)提供了豐富的測(cè)試框架支持,包括測(cè)試用例的setUp和tearDown方法,在實(shí)現(xiàn)用例的過(guò)程中可以重寫。依托頁(yè)面管理和公共庫(kù)模塊實(shí)現(xiàn)的頁(yè)面方法和公共函數(shù),每一個(gè)測(cè)試用例腳本的書寫都會(huì)非常清晰簡(jiǎn)潔,一個(gè)簡(jiǎn)單的Floor Manager Lite的登錄用例如下:

class Test_TC_Login(unittest.TestCase): 
  def setUp(self): 
    self.driver = webdriver.Chrome(cc.driverPath()) 
    self.base_url = cc.baseUrl() 
    self.testCaseInfo = TestCaseInfo(id=1,name="Test case name",owner='xua') 
    self.testResult = TestReport() 
    LogUtility.CreateLoggerFile("Test_TC_Login") 
  def test_A(self): 
    try: 
      self.testCaseInfo.starttime = cc.getCurrentTime() 
      #Step1: open base site 
      LogUtility.Log("Open Base site"+self.base_url) 
      self.driver.get(self.base_url) 
 
      #Step2: Open Login page 
      login_page = LoginPage(self.driver) 
 
      #Step3: Enter username & password 
      LogUtility.Log("Login web using username") 
      login_page.set_username("username") 
      login_page.set_password("password") 
 
      time.sleep(2) 
      #Checkpoint1: Check popup dialog title 
      LogUtility.Log("Check whether sign in dialog exists or not") 
      self.assertEqual(login_page.get_DiaglogTitle(),"Sign in") 
 
      #time.sleep(3) 
      #Step4: Cancel dialog 
      login_page.click_cancel() 
      self.testCaseInfo.result = "Pass" 
 
    except Exception as err: 
      self.testCaseInfo.errorinfo = str(err) 
      LogUtility.Log(("Got error: "+str(err))) 
    finally: 
      self.testCaseInfo.endtime = cc.getCurrentTime() 
      self.testCaseInfo.secondsDuration = cc.timeDiff(self.testCaseInfo.starttime,self.testCaseInfo.endtime) 
  def tearDown(self): 
    self.driver.close() 
    self.testResult.WriteHTML(self.testCaseInfo) 
 
if __name__ == '__main__': 
  unittest.main()

從這個(gè)測(cè)試用例中,我們可以看到

1.Setup中定義了執(zhí)行測(cè)試用例前的一些實(shí)例化工作
2.tearDown對(duì)執(zhí)行完測(cè)試做了清理和寫日志文件工作
3.測(cè)試步驟、測(cè)試數(shù)據(jù)和測(cè)試檢查點(diǎn)非常清晰,易修改(比如用戶名密碼)
4.日志級(jí)別僅有Debug,所以寫日志僅需用同一Log方法

3.3.4 用例執(zhí)行模塊(控制器)

執(zhí)行模塊主要用來(lái)控制測(cè)試用例腳本的批量執(zhí)行,形成一個(gè)測(cè)試集。用例的執(zhí)行引用了Python標(biāo)準(zhǔn)庫(kù)中的subprocess來(lái)執(zhí)行nosetests的shell命令,從而執(zhí)行給定測(cè)試用例集中的用例。測(cè)試用例集是一個(gè)簡(jiǎn)單的純文本文件,實(shí)現(xiàn)過(guò)程中利用了.txt文件testcases.txt:

Test_Login_pass.py 
Test_Login_Fail.py 
#Test_MainPage_CheckSecurityTableInfo.py 
Test_MainPage_EditSecurityInfo.py

用例前沒(méi)有“#“標(biāo)記的測(cè)試用例腳本會(huì)被執(zhí)行,而有”#“標(biāo)記的則會(huì)被忽略,這樣可以很方便的控制測(cè)試集的執(zhí)行,當(dāng)然也可以創(chuàng)建不同的文件來(lái)執(zhí)行不同的測(cè)試集。

具體的調(diào)用代碼如下:

def LoadAndRunTestCases(self): 
  try: 
    f = open(self.testcaselistfile) 
    testfiles = [test for test in f.readlines() if not test.startswith("#")] 
    f.close() 
    for item in testfiles: 
      subprocess.call("nosetests "+str(item).replace("\\n",""),shell = True) 
  except Exception as err: 
    LogUtility.logger.debug("Failed running test cases, error message: {}".format(str(err))) 
  finally: 
    EmailUtils.send_report()

3.4 執(zhí)行結(jié)果

測(cè)試用例執(zhí)行完畢后主要有兩種輸出:日志和測(cè)試報(bào)告。測(cè)試報(bào)告會(huì)html附件的形式通過(guò)郵件發(fā)出,例如:

4 需要改進(jìn)的模塊

對(duì)于現(xiàn)有實(shí)現(xiàn)的測(cè)試框架,已經(jīng)可以滿足web對(duì)象的自動(dòng)化需求,但還是有些可以改進(jìn)提高的地方,比如:

針對(duì)部分測(cè)試用例是否可以嘗試數(shù)據(jù)驅(qū)動(dòng)添加屏幕截圖功能封裝selenium中By庫(kù)中的函數(shù),以便更高效的定位頁(yè)面元素等結(jié)合業(yè)界優(yōu)秀的自動(dòng)化框架和實(shí)踐持續(xù)改進(jìn)

5 總結(jié)

基于selenium實(shí)現(xiàn)的web自動(dòng)化框架不僅輕量級(jí)而且靈活,可以快速的開發(fā)自動(dòng)化測(cè)試用例。結(jié)合本篇中的框架設(shè)計(jì)以及一些好的實(shí)踐,希望對(duì)大家以后的web自動(dòng)化框架的設(shè)計(jì)和實(shí)現(xiàn)有所幫助。

源代碼:https://github.com/AlvinXuCH/WebAutomaiton

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • python分割文件的常用方法

    python分割文件的常用方法

    這篇文章主要介紹了python分割文件的常用方法,包括指定分割大小、按行分割與分割合并等技巧,非常實(shí)用,需要的朋友可以參考下
    2014-11-11
  • PyQt5實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器

    PyQt5實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了PyQt5實(shí)現(xiàn)簡(jiǎn)單的計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • python 使用元類type創(chuàng)建類

    python 使用元類type創(chuàng)建類

    這篇文章主要介紹了Python 使用元類type創(chuàng)建類,結(jié)合實(shí)例形式詳細(xì)分析了Python元類的概念、功能及元類type創(chuàng)建類對(duì)象的常見應(yīng)用技巧,需要的朋友可以參考一下文章的具體內(nèi)容。希望對(duì)你有所幫助
    2021-10-10
  • Python實(shí)現(xiàn)目錄自動(dòng)清洗

    Python實(shí)現(xiàn)目錄自動(dòng)清洗

    這篇文章主要為大家詳細(xì)介紹了Python實(shí)現(xiàn)目錄自動(dòng)清洗的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-11-11
  • python數(shù)據(jù)結(jié)構(gòu):數(shù)據(jù)類型

    python數(shù)據(jù)結(jié)構(gòu):數(shù)據(jù)類型

    這篇文章主要介紹了python數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù)類型,在?Python?以及其他所有面向?qū)ο缶幊陶Z(yǔ)言中,類都是對(duì)數(shù)據(jù)的構(gòu)成(狀態(tài))以及數(shù)據(jù)?能做什么(行為)的描述,下面我們就來(lái)你看看python數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù)類型商務(wù)詳細(xì)介紹,需要的小伙伴可以參考一下
    2021-12-12
  • Python pyinotify模塊實(shí)現(xiàn)對(duì)文檔的實(shí)時(shí)監(jiān)控功能方法

    Python pyinotify模塊實(shí)現(xiàn)對(duì)文檔的實(shí)時(shí)監(jiān)控功能方法

    今天小編就為大家分享一篇Python pyinotify模塊實(shí)現(xiàn)對(duì)文檔的實(shí)時(shí)監(jiān)控功能方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10
  • 如何搭建pytorch環(huán)境的方法步驟

    如何搭建pytorch環(huán)境的方法步驟

    這篇文章主要介紹了如何搭建pytorch環(huán)境的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • widows下安裝pycurl并利用pycurl請(qǐng)求https地址的方法

    widows下安裝pycurl并利用pycurl請(qǐng)求https地址的方法

    今天小編就為大家分享一篇widows下安裝pycurl并利用pycurl請(qǐng)求https地址的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10
  • pycharm的python_stubs問(wèn)題

    pycharm的python_stubs問(wèn)題

    這篇文章主要介紹了pycharm的python_stubs問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-04-04
  • python程序調(diào)用遠(yuǎn)程服務(wù)的步驟詳解

    python程序調(diào)用遠(yuǎn)程服務(wù)的步驟詳解

    這篇文章主要介紹了python程序調(diào)用遠(yuǎn)程服務(wù)的步驟詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-03-03

最新評(píng)論