您好,登錄后才能下訂單哦!
1 什么是selenium
Selenium 是一個基于瀏覽器的自動化工具,它提供了一種跨平臺、跨瀏覽器的端到端的web自動化解決方案。Selenium主要包括三部分:Selenium IDE、Selenium WebDriver 和Selenium Grid:
本文中主要使用python結合Selenium WebDriver庫進行自動化測試框架的搭建。
2 自動化測試框架
一個典型的自動化測試框架一般包括用例管理模塊、自動化執行控制器、報表生成模塊和日志模塊等,這些模塊之間不是相互孤立的,而是相輔相成的。
下面來介紹下每個模塊的邏輯單元:
用例管理模塊包括用例的添加、修改、刪除等操作單元,這些單元也會涉及到用例書寫的模式,測試數據的管理、可復用庫等
控制器是自動化用例執行的組織模塊,主要負責以什么方式去執行用例。比較典型的控制器有用戶圖形界面(GUI)和“commandline+文件”兩種。
報表生成模塊主要負責執行完用例以后生成報表,報表一般以HTML格式居多,信息主要包括用例的執行情況及相應的總結報告。另外還可以添加發送郵件功能。
日志模塊主要用來記錄用例的執行情況,以便于更高效的調查用例失敗信息及追蹤用例執行情況。
3 自動化框架的設計與實現
3.1 需求分析
測試對象是一個典型的后臺系統的Web展現平臺,基于此平臺設計的自動化框架要包含測試用例管理、測試執行控制、測試報表及測試日志的生成,整體測試框架要輕量易用。
3.2 概要設計
概要設計包括了四個大的模塊:公共庫模塊(可復用函數、日志管理、報表管理以及發送郵件管理)、用例倉庫(具體用例的管理)、頁面管理(單獨對Web頁面進行抽象,封裝頁面元素和操作方法)以及執行模塊。
概要設計類圖:
3.3 詳細設計與實現
3.3.1 頁面管理
測試Web對象是一個典型的單頁面應用,因此采用頁面模式(page pattern)來進行組織:
頁面模式是頁面與測試用例之間的橋梁,它將每個頁面抽象成一個單獨的頁面類,為測試用例提供頁面元素的定位和操作。
頁面模式的類圖如下:
BasePage作為基類只包含一個driver成員變量,它用來標記Selenium中的WebDriver,以便在BasePage的派生類中定位頁面元素。LoginPage和PageN等作為派生類,可以提供相應頁面元素的定位和操作方法。比如測試對象的登錄頁面:
從頁面可以看出,需要操作的頁面元素分別為:Username,Password,remember my username checkbox和Sign in按鈕,它們對應的操作為輸入用戶名和密碼,點選checkbox和點擊Sign In按鈕,具體代碼級別的實現如下:
頁面基類BasePage.py:
class BasePage(object): """description of class""" #webdriver instance def __init__(self, driver): self.driver = driver
LoginPage頁面繼承自BasePage,并進行Login Page的元素定位及操作實現。代碼中定位了username和password,并且添加了設置用戶名和密碼的操作。
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://h4[@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()
采用頁面模式來管理頁面和測試用例有很多好處,主要體現在:
每個頁面都有單獨的類來封裝頁面元素和操作,讓頁面操作更加具體化,而不是相對獨立的。
比如未使用頁面模式,測試用例的輸入用戶名和密碼的代碼:
#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)
使用頁面模式之后,輸入用戶名和密碼的代碼:
#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")
通過對比我們不難發現,未使用頁面模式的代碼組織比較混亂,步驟多,可讀性非常差,不難想象,一個通篇都是find_element_by_id或者send_Keys的測試用例到底有多糟糕!而使用了頁面模式之后,在哪個頁面做什么操作都非常清晰,非常接近測試用例的步驟,易讀性非常好。
由于頁面操作都被封裝在了頁面類中,所以頁面方法和容易調用,可復用性非常好。而未使用頁面模式的用例只能每次都實現一遍。
由于測試目標頁面的多變性,頁面元素的定位經常需要改變,利用了頁面模式后,只需要修改一遍其頁面類中的定位就可以對所用用到該元素的測試用例生效;而在未使用該模式的情況下,必須修改每一個用到該元素的測試用例,非常容易遺漏,工作量也非常大。
綜合以上頁面模式的各種優點,我們在以后的web自動化中可以多使用該模式來組織頁面。
3.3.2 公共庫模塊
公共庫模塊是為創建測試用例服務的,它主要包括常量、公共函數、日志管理、報表管理以及發送郵件管理等。
公共庫模塊涉及到的功能一般多而雜,在設計的時候只要遵循高內聚低耦合就可以了。比如常量、變量和一些公共函數可以放在同一個文件中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)
測試用例信息類用來標識測試用例,并且包括執行用例執行結果信息,主要包括以下字段:
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
測試用例信息需要在每個測試用例中實例化,以便對測試用例進行標記,并最終體現在測試報告中。
日志主要用來記錄測試用例執行步驟及產生的錯誤信息,不同的信息有不同的日志級別,比如Information,Warning,Critical和Debug。由于每個測試用例產生的日志條目比較少,所以在測試框架中只利用了最高級別的日志打印,即Debug級別,該級別也會將其他所有的日志級別的信息同樣打印出來。在具體的實現中引用了Python標準庫中的logging類庫,以便更方便的控制日志輸出:
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)
報表管理及發送郵件模塊實現了報表(html格式)的生成及自動發送郵件的功能。報表和郵件依附于當前測試的執行,每次執行都會獨立的觸發報表生成和郵件發送。該模塊主要運用了Python中的lxml、smtplib和email庫。
3.3.3 用例倉庫
用例倉庫主要用來組織自動化測試用例。每條測試用例都被抽象成一個獨立的類,并且均繼承自unittest.TestCase類。 Python中的unittest庫提供了豐富的測試框架支持,包括測試用例的setUp和tearDown方法,在實現用例的過程中可以重寫。依托頁面管理和公共庫模塊實現的頁面方法和公共函數,每一個測試用例腳本的書寫都會非常清晰簡潔,一個簡單的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()
從這個測試用例中,我們可以看到
1.Setup中定義了執行測試用例前的一些實例化工作
2.tearDown對執行完測試做了清理和寫日志文件工作
3.測試步驟、測試數據和測試檢查點非常清晰,易修改(比如用戶名密碼)
4.日志級別僅有Debug,所以寫日志僅需用同一Log方法
3.3.4 用例執行模塊(控制器)
執行模塊主要用來控制測試用例腳本的批量執行,形成一個測試集。用例的執行引用了Python標準庫中的subprocess來執行nosetests的shell命令,從而執行給定測試用例集中的用例。測試用例集是一個簡單的純文本文件,實現過程中利用了.txt文件testcases.txt:
Test_Login_pass.py Test_Login_Fail.py #Test_MainPage_CheckSecurityTableInfo.py Test_MainPage_EditSecurityInfo.py
用例前沒有“#“標記的測試用例腳本會被執行,而有”#“標記的則會被忽略,這樣可以很方便的控制測試集的執行,當然也可以創建不同的文件來執行不同的測試集。
具體的調用代碼如下:
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 執行結果
測試用例執行完畢后主要有兩種輸出:日志和測試報告。測試報告會html附件的形式通過郵件發出,例如:
4 需要改進的模塊
對于現有實現的測試框架,已經可以滿足web對象的自動化需求,但還是有些可以改進提高的地方,比如:
針對部分測試用例是否可以嘗試數據驅動添加屏幕截圖功能封裝selenium中By庫中的函數,以便更高效的定位頁面元素等結合業界優秀的自動化框架和實踐持續改進
5 總結
基于selenium實現的web自動化框架不僅輕量級而且靈活,可以快速的開發自動化測試用例。結合本篇中的框架設計以及一些好的實踐,希望對大家以后的web自動化框架的設計和實現有所幫助。
源代碼:https://github.com/AlvinXuCH/WebAutomaiton
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。