在寫完上一篇“基於Selenium的Web自動化框架”(http://www.cnblogs.com/AlwinXu/p/5836709.html)之后一直沒有時間重新審視該框架,正好趁着給同事分享的機會,重新分析了一下框架,發現了很多不足之處,所以才有了這篇增強版。
到底在框架的哪一部分做了增強呢?這次主要從設計模式的角度來簡單介紹一下。
首先我們來看一下之前是如何書寫頁面模式中的類的:
BasePage:
class BasePage(object): """description of class""" #webdriver instance def __init__(self, driver): self.driver = driver
GoogleMainPage:
from BasePage import BasePage from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys class GoogleMainPage(BasePage): """description of class""" searchbox = (By.ID,'lst-ib') def inputSearchContent(self,searchContent): searchBox = self.driver.find_element(*self.searchbox) searchBox.send_keys(searchContent+Keys.RETURN)
重新審視之前的實現,我們可以發現在各個子類頁面中,均需要引用相當的selenium類庫(比如webdriver),並且需要用webdriver來定位頁面元素,這就會造成各個子類頁面與selenium類庫有較多的集成,並且也是書寫上的浪費。
現在來看一下做了結構調整的部分呈現:
BasePage:
from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains from selenium.common.exceptions import StaleElementReferenceException from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys class BasePage(object): """description of class""" #webdriver instance def __init__(self, browser='chrome'): ''' initialize selenium webdriver, use chrome as default webdriver ''' if browser == "firefox" or browser == "ff": driver = webdriver.Firefox() elif browser == "chrome": driver = webdriver.Chrome() elif browser == "internet explorer" or browser == "ie": driver = webdriver.Ie() elif browser == "opera": driver = webdriver.Opera() elif browser == "phantomjs": driver = webdriver.PhantomJS() try: self.driver = driver except Exception: raise NameError("Not found %s browser,You can enter 'ie', 'ff' or 'chrome'." % browser) def findElement(self,element): ''' Find element element is a set with format (identifier type, value), e.g. ('id','username') Usage: self.findElement(element) ''' try: type = element[0] value = element[1] if type == "id" or type == "ID" or type=="Id": elem = self.driver.find_element_by_id(value) elif type == "name" or type == "NAME" or type=="Name": elem = self.driver.find_element_by_name(value) elif type == "class" or type == "CLASS" or type=="Class": elem = self.driver.find_element_by_class_name(value) elif type == "link_text" or type == "LINK_TEXT" or type=="Link_text": elem = self.driver.find_element_by_link_text(value) elif type == "xpath" or type == "XPATH" or type=="Xpath": elem = self.driver.find_element_by_xpath(value) elif type == "css" or type == "CSS" or type=="Css": elem = self.driver.find_element_by_css_selector(value) else: raise NameError("Please correct the type in function parameter") except Exception: raise ValueError("No such element found"+ str(element)) return elem def findElements(self,element): ''' Find elements element is a set with format (identifier type, value), e.g. ('id','username') Usage: self.findElements(element) ''' try: type = element[0] value = element[1] if type == "id" or type == "ID" or type=="Id": elem = self.driver.find_elements_by_id(value) elif type == "name" or type == "NAME" or type=="Name": elem = self.driver.find_elements_by_name(value) elif type == "class" or type == "CLASS" or type=="Class": elem = self.driver.find_elements_by_class_name(value) elif type == "link_text" or type == "LINK_TEXT" or type=="Link_text": elem = self.driver.find_elements_by_link_text(value) elif type == "xpath" or type == "XPATH" or type=="Xpath": elem = self.driver.find_elements_by_xpath(value) elif type == "css" or type == "CSS" or type=="Css": elem = self.driver.find_elements_by_css_selector(value) else: raise NameError("Please correct the type in function parameter") except Exception: raise ValueError("No such element found"+ str(element)) return elem def open(self,url): ''' Open web url Usage: self.open(url) ''' if url != "": self.driver.get(url) else: raise ValueError("please provide a base url") def type(self,element,text): ''' Operation input box. Usage: self.type(element,text) ''' element.send_keys(text) def enter(self,element): ''' Keyboard: hit return Usage: self.enter(element) ''' element.send_keys(Keys.RETURN) def click(self,element): ''' Click page element, like button, image, link, etc. ''' element.click() def quit(self): ''' Quit webdriver ''' self.driver.quit() def getAttribute(self, element, attribute): ''' Get element attribute ''' return element.get_attribute(attribute) def getText(self, element): ''' Get text of a web element ''' return element.text def getTitle(self): ''' Get window title ''' return self.driver.title def getCurrentUrl(self): ''' Get current url ''' return self.driver.current_url def getScreenshot(self,targetpath): ''' Get current screenshot and save it to target path ''' self.driver.get_screenshot_as_file(targetpath) def maximizeWindow(self): ''' Maximize current browser window ''' self.driver.maximize_window() def back(self): ''' Goes one step backward in the browser history. ''' self.driver.back() def forward(self): """ Goes one step forward in the browser history. """ self.driver.forward() def getWindowSize(self): """ Gets the width and height of the current window. """ return self.driver.get_window_size() def refresh(self): ''' Refresh current page ''' self.driver.refresh() self.driver.switch_to()
GoogleMainPage:
from BasePage import BasePage class GoogleMainPage(BasePage): """description of class""" searchbox = ('ID','lst-ib') def __init__(self, browser = 'chrome'): super().__init__(browser) def inputSearchContent(self,searchContent): searchBox = self.findElement(self.searchbox) self.type(searchBox,searchContent) self.enter(searchBox)
Test
所做的改變:
- 將與Selenium類庫相關的操作做二次封裝,放在BasePage中,其他子類頁面自動繼承相應的操作方法(如findelement,click等等)
- 封裝了findelement方法,可以根據頁面元素的(類型,值)進行查找,只需要調用一個方法findelement(s),而不需要針對不同的類型調用不同的find方法(fine_element_by_xxxx())
- 子類頁面不需要引用selenium的類庫,書寫更加簡單易讀
- 測試用例中也不需要引用selenium的任何類庫,簡單易讀
代碼已更新到GitHub:https://github.com/AlvinXuCH/WebAutomaiton 歡迎提供改進意見