欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

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

系統(tǒng) 1617 0

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)表生成模塊和日志模塊等,這些模塊之間不是相互孤立的,而是相輔相成的。

python基于Selenium的web自動(dòng)化框架_第1張圖片

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

  • 用例管理模塊

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

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

控制器是自動(dòng)化用例執(zhí)行的組織模塊,主要負(fù)責(zé)以什么方式去執(zhí)行用例。比較典型的控制器有用戶(hù)圖形界面(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ì)類(lèi)圖:

python基于Selenium的web自動(dòng)化框架_第2張圖片

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)行組織:

python基于Selenium的web自動(dòng)化框架_第3張圖片

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

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

python基于Selenium的web自動(dòng)化框架_第4張圖片

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

python基于Selenium的web自動(dòng)化框架_第5張圖片

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

頁(yè)面基類(lèi)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è)置用戶(hù)名和密碼的操作。

            
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)來(lái)封裝頁(yè)面元素和操作,讓頁(yè)面操作更加具體化,而不是相對(duì)獨(dú)立的。

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

            
 #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è)面模式之后,輸入用戶(hù)名和密碼的代碼:

            
#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è)面類(lèi)中,所以頁(yè)面方法和容易調(diào)用,可復(fù)用性非常好。而未使用頁(yè)面模式的用例只能每次都實(shí)現(xiàn)一遍。

  • 可維護(hù)性好

由于測(cè)試目標(biāo)頁(yè)面的多變性,頁(yè)面元素的定位經(jīng)常需要改變,利用了頁(yè)面模式后,只需要修改一遍其頁(yè)面類(lèi)中的定位就可以對(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)用來(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類(lèi)庫(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ú)立的類(lèi),并且均繼承自u(píng)nittest.TestCase類(lèi)。 Python中的unittest庫(kù)提供了豐富的測(cè)試框架支持,包括測(cè)試用例的setUp和tearDown方法,在實(shí)現(xiàn)用例的過(guò)程中可以重寫(xiě)。依托頁(yè)面管理和公共庫(kù)模塊實(shí)現(xiàn)的頁(yè)面方法和公共函數(shù),每一個(gè)測(cè)試用例腳本的書(shū)寫(xiě)都會(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è)試做了清理和寫(xiě)日志文件工作
3.測(cè)試步驟、測(cè)試數(shù)據(jù)和測(cè)試檢查點(diǎn)非常清晰,易修改(比如用戶(hù)名密碼)
4.日志級(jí)別僅有Debug,所以寫(xiě)日志僅需用同一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ā)出,例如:

python基于Selenium的web自動(dòng)化框架_第6張圖片

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

對(duì)于現(xiàn)有實(shí)現(xiàn)的測(cè)試框架,已經(jīng)可以滿(mǎn)足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í)而且靈活,可以快速的開(kāi)發(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í)有所幫助,也希望大家多多支持腳本之家。


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 波多野中文字幕s | 国产资源一区 | 三级网页 | 美国一级片免费看 | 国产精品中文在线 | 天天成人综合网 | jizzjizz视频| 天天干夜夜爽 | 日本香蕉一区二区三区 | A片太大太长太深好爽A片视频 | 日韩欧美一区在线观看 | 日本高清在线精品一区二区三区 | naruto henta| 日产国产欧美视频一区精品 | 国内精品免费一区二区观看 | 国产免费播放一区二区 | av毛片| 亚洲综合欧美日韩 | 午夜资源在线 | 亚洲午夜精品久久久久久成年 | 久久综合婷婷香五月 | 国产精品视频在线观看 | 日韩欧美一区二区三区不卡在线 | 三级国产 | 国产精品国产三级在线专区 | 高清国产一区二区三区 | 免费在线日韩 | 学院传说之三生三世桃花缘 | 538prom国产在线视频一区 | 久久国产a | 日韩经典欧美一区二区三区 | 婷婷丁香社区 | 超级97碰碰碰碰久久久久最新 | 久久久久国产 | 日韩欧美片 | 日本黄大片视频在线播放 | 国产亚洲欧美一区 | 中文字幕 欧美 日韩 | 欧洲一级视频 | 黄色免费av | 亚洲在线播放视频 |