[笔记]Selenium Testing Tools Cookbook_Chapter9

Chapter9 Extending Selenium

9.1 Creating an extension class for web tables

Create a new class WebTable, which we will use to implement support for the table elements

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException

class WebTable:
    def __init__(self,webTable):
        self._webTable = webTable

    # retrieve rows
    def getRowCount(self):
        self.tableRows = self._webTable.find_elements_by_tag_name('tr')
        return len(self.tableRows)

    #retrieve columns
    def getColumnCount(self):
        self.tableRows = self._webTable.find_elements_by_tag_name('tr')
        self.headerRow = self.tableRows[0]
        self.tableCols = self.headerRow.find_elements_by_tag_name('td')
        return len(self.tableCols)

    # retrieve data from a specific cell of the table
    def getCellData(self,rowIdx,colIdx):
        self.tableRows = self._webTable.find_elements_by_tag_name('tr')
        self.currentRow = self.tableRows[rowIdx-1]
        self.tableCols = self.currentRow.find_elements_by_tag_name('td')
        self.cell = self.tableCols[colIdx-1]
        return self.cell.text

    # retrieve the cell editor element
    def getCellEditor(self,rowIdx,colIdx,editorIdx):
        try:
            self.tableRows = self._webTable.find_elements_by_tag_name('tr')
            self.currentRow = self.tableRows[rowIdx-1]
            self.tableCols = self.currentRow.find_elements_by_tag_name('td')
            self.cell = self.tableCols[colIdx-1]
            self.cellEditor = self.cell.find_elements_by_tag_name('input')[editorIdx]
            return self.cellEditor
        except NoSuchElementException:
            raise NoSuchElementException('Failed to get cell editor')

Create a Test Class:

import unittest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from WebTable import WebTable

class WebTableTests(unittest.TestCase):
    def setUp(self):
        chrome_options = Options()
        chrome_options.add_argument('--no-sandbox')   #让chrome在root权限下跑
        chrome_options.add_argument('--disable-dev-shm-usage') 
        chrome_options.add_experimental_option('useAutomationExtension',False)
        self.driver = webdriver.Chrome(executable_path='D:/elf_private/test/chromedriver',options=chrome_options)
        self.driver.implicitly_wait(30)
        self.driver.maximize_window()
        self.driver.get("file:///D:/elf_private/test/sele/table_example.html")

    def testWebTableTest(self):
        self.table = WebTable(self.driver.find_element_by_tag_name('table'))
        print('Table Row Count: ' + str(self.table.getRowCount()))
        print('Table Column Count: ' + str(self.table.getColumnCount()))
        print('Row3 Col1 is ' + self.table.getCellData(2,1))

    def tearDown(self):
        self.driver.quit()

if __name__ == '__main__':
    unittest.main()

9.2 Creating an extension for the jQueryUI tab widget

Example jQuery UI tabs widget: http://jqueryui.com/demos/tabs/
Create a JQueryUITab class to represent the tab widget

from selenium import webdriver

class JQueryUITab:
    def __init__(self,jQueryUITab):
        self._jQueryUITab = jQueryUITab

    def getTabCount(self):
        self.tabs = self._jQueryUITab.find_elements_by_css_selector(".ui-tabs-nav > li")
        return len(self.tabs)

    def getSelectedTab(self):
        self.tab = self._jQueryUITab.\
        find_element_by_css_selector(".ui-tabs-nav > li[class*='ui-state-active']")
        return self.tab.text

    def selectTab(self,driver,tabName):
        self.idx = 0
        self.found = False
        self.tabs = self._jQueryUITab.find_elements_by_css_selector(".ui-tabs-nav > li")
        for tab in self.tabs:
            if tab.text == tabName:
                driver.execute_script(\
                    "jQuery(arguments[0]).tabs().tabs('option','active',arguments[1]);",\
                    self._jQueryUITab,self.idx)
                self.found = True
                break
            idx += 1
        if self.found == False:
            raise IllegalArgumentException("Could not find tab '" + tabName +"'")

test code:

import unittest
from selenium import webdriver
from JQueryUITab import JQueryUITab

class WebTableTests(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox(executable_path='/usr/local/bin/geckodriver')
        self.driver.implicitly_wait(30)
        self.driver.maximize_window()
        self.driver.get("file:///Users/elf/selenium/jquery/index.html")

    def testJianShu(self):
        self.tab = JQueryUITab(self.driver.find_element_by_css_selector("div#tabs"))
        print(str(self.tab.getTabCount()))
        self.tab.selectTab(self.driver,"First")
        print(self.tab.getSelectedTab())

    def tearDown(self):
        self.driver.quit()

if __name__ == '__main__':
    unittest.main()

9.3 Implementing an extension for the WebElement object to set the element attribute values

Setting an element's attribute can be useful in various situations where the test needs to manipulate properties of an element. For example, for a masked textbox, the send_keys() method may not work well, and setting the value of the textbox will help to overcome these issues.
setAttribute() method:

class WebElementExtender:
    @staticmethod
    def setAttribute(driver,element,attributeName,value):
        driver.execute_script("arguments[0].setAttribute(arguments[1],arguments[2])",\
            element,attributeName,value)

An example on using this method:
In this case, this can be done by clear() and send_keys()

search = driver.find_element_by_id("q")
WebElementExtender.setAttribute(driver,search,"placeholder","abc")

9.4 Implementing an extension for the WebElement object to highlight elements

highlightElement method

@staticmethod
def highlightElement(driver,element):
    driver.execute_script("arguments[0].setAttribute('style',arguments[1]);",\
        element,"background:green ;border:2px solid red;")

An example on using this method:

search = driver.find_element_by_id("q")

WebElementExtender.highlightElement(driver,search)
# wait 3s to see the highlight effect
time.sleep(3)
search.send_keys("abc")

9.5 Creating an object map for Selenium tests

Create a .xml file to store the elements


    
        SignUp
        id
        sign_up
    
    
        SignIn
        id
        sign_in
    
    
        Download
        classname
        app-download-btn
    
    
        SearchArea
        name
        q
    
    
        SearchButton
        classname
        search-btn
    

Implement the ObjectMap class to read the xml file and provide the locator information to the test

from selenium import webdriver
from xml.dom.minidom import parse

class ObjectMap:
    def __init__(self,mapFile):
        self.domTree = parse(mapFile)
        self.rootNode = self.domTree.documentElement

    def getLocator(self,driver,logicalElementName):
        self.locators = self.rootNode.getElementsByTagName("element")
        for locator in self.locators:
            #print(locator.getElementsByTagName("name")[0].childNodes[0].data)
            if locator.getElementsByTagName("name")[0].childNodes[0].data == logicalElementName:
                try:
                    self.locatorType = locator.getElementsByTagName("type")[0].childNodes[0].data
                    self.locatorValue = locator.getElementsByTagName("value")[0].childNodes[0].data
                    return self.getLocatorByType(driver)
                except Exception:
                    raise Exception("Failed to generate locator for '" + logicalElementName + "'")

    def getLocatorByType(self,driver):
        if self.locatorType.lower() == "id":
            return driver.find_element_by_id(self.locatorValue)
        elif self.locatorType.lower() == "name":
            return driver.find_element_by_name(self.locatorValue)
        elif self.locatorType.lower() == "classname":
            return driver.find_element_by_class_name(self.locatorValue)
        elif self.locatorType.lower() == "linktext":
            return driver.find_element_by_link_text(self.locatorValue)
        elif self.locatorType.lower() == "partiallinktext":
            return driver.find_element_by_partial_link_text(self.locatorValue)
        elif self.locatorType.lower() == "css":
            return driver.find_element_by_css_selector(self.locatorValue)
        elif self.locatorType.lower() == "xpath":
            return driver.find_element_by_xpath(self.locatorValue)
        elif self.locatorType.lower() == "tagname":
            return driver.find_element_by_tag_name(self.locatorValue)
        else:
            raise Exception("Locator Type '" + self.locatorType +"' not supported!")

Create a test code:

import unittest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from ObjectMap import ObjectMap

class WebTableTests(unittest.TestCase):
    def setUp(self):
        chrome_options = Options()
        chrome_options.add_argument('--no-sandbox')   #让chrome在root权限下跑
        chrome_options.add_argument('--disable-dev-shm-usage') 
        chrome_options.add_experimental_option('useAutomationExtension',False)
        self.driver = webdriver.Chrome(executable_path='D:/elf_private/test/chromedriver',options=chrome_options)
        self.driver.implicitly_wait(30)
        self.driver.maximize_window()
        #self.driver.get("file:///D:/elf_private/test/sele/table_example.html")
        self.driver.get("https://www.jianshu.com")

    def testJianShu(self):
        self.map = ObjectMap('mapFile.xml')
        print(self.map.getLocator(self.driver,"SignUp").text)
        print(self.map.getLocator(self.driver,"SignIn").text)
        print(self.map.getLocator(self.driver,"Download").text)
        Search_Area = self.map.getLocator(self.driver,"SearchArea")
        Search_Area.send_keys("abc")
        Button = self.map.getLocator(self.driver,"SearchButton")
        Button.click()

    def tearDown(self):
        self.driver.quit()

if __name__ == '__main__':
    unittest.main()

9.6 Capturing screenshots of elements in the Selenium WebDriver

There are screenshot APIs in selenium for Python. So no need to create interface ourselves ^_^

  • selenium.webdriver.remote.webdriver
    • get_screenshot_as_base64()
    • get_screenshot_as_file(filename)
    • get_screenshot_as_png()
  • selenium.webdriver.remote.webelement
    • screenshot(filename)
    • screenshot_as_base64
    • screenshot_as_png
button = driver.find_element_by_id("sign_up")
# get the screenshot of the button
button.screenshot('signup.png')
# get the screenshot of the current window
driver.get_screenshot_as_file('currentwindow.png')

9.7 Comparing images in Selenium

use PIL module for python
Implement Compare class to compare two images

from PIL import Image
from PIL import ImageChops

class Compare:
    @staticmethod
    def CompareImage(PathOne,PathTwo,DiffPath):
        ImgOne = Image.open(PathOne)
        ImgTwo = Image.open(PathTwo)
        try:
            DiffImg = ImageChops.difference(ImgOne,ImgTwo)
            if DiffImg.getbbox() is None:
                print("Images are same!")
            else:
                DiffImg.save(DiffPath)
        except ValueError as e:
            raise ValueError("Paste another image into this image.")

test code:

self.driver.get_screenshot_as_file("New.png")
Compare.CompareImage("Base.png","New.png","Diff.png")

9.8 Measuring performance with the Navigation Timing API

Navigation Timing is a W3C Standard JavaScript API to measure performance on the Web. The API provides a simple way to get accurate and detailed timing statistics natively for page navigation and load events. It is available on IE9, Google Chrome, Firefox and WebKit-based browsers.
The API is accessed via the properties of the timing interface of the window.performance object using JavaScript

driver.get("https://www.jianshu.com")
# get the Load Event End
loadEventEnd = driver.execute_script("return window.performance.timing.loadEventEnd")
# get the Navigation Event Start
navigationStart = driver.execute_script("return window.performance.timing.navigationStart")
# print Page Load Time
print("Page Load Time is " + str((loadEventEnd - navigationStart)/1000) + " seconds.")

你可能感兴趣的:([笔记]Selenium Testing Tools Cookbook_Chapter9)