Base class
The base class contains generic and reusable methods and these methods are nothing but wrappers developed on top of selenium webdriver classes and methods.
The following code depicts a base class having few generic, static and reusable methods defined.
from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.common.keys import Keysfrom selenium.webdriver.support.wait import WebDriverWaitfrom selenium.common.exceptions import *import utilities.logger as climport inspectfrom traceback import print_stackimport timefrom datetime import datetimeimport osfrom selenium.webdriver.support.ui import Selectfrom selenium.webdriver import ActionChainsimport logging# This is a base class class SeleniumDriver(): """ This is a base class containing all the generic/reusable and static methods """ # Object of logger class log_base = cl.customlogger(loglevel=logging.DEBUG) # Constructor to initialize driver def __init__(self, driver): self.driver = driver def get_by_type(self, locatorType): """ This method will return the by type for the locatorType argument. ================================================================= Parameter: ---------- 1. Required: 1. locatorType: [id, name, class, link-text, xpath, css, tag etc.] Return: ------- It returns By locator types e.g. By.ID, By.NAME etc. Exception: ---------- Error if locatorType is not correct/supported """ log_base = cl.customlogger(loglevel=logging.DEBUG) locatorType = locatorType.lower() if locatorType == 'id': return By.ID if locatorType == 'name': return By.NAME if locatorType == 'class': return By.CLASS_NAME if locatorType == 'link-text': return By.LINK_TEXT if locatorType == 'xpath': return By.XPATH if locatorType == 'css': return By.CSS_SELECTOR if locatorType == 'tag': return By.TAG_NAME else: self.log_base.info("[FAIL] Test method '{0}-->{1}".format(__name__, inspect.currentframe().f_code.co_name) + "Locator type " + locatorType + " not correct/supported") return False def get_element(self, locator, locatorType="id"):""" This method will find out an element according to the combination of locator and locatorType. ============================================================================================= Parameter:---------- 1. Required 1. locator 2. locatorType Return: ------- Element Exception: ---------- NoSuchElementException """ element = None try: locatorType = locatorType.lower() byType = self.get_by_type(locatorType) element = self.driver.find_element(byType, locator) self.log_base.info("[PASS] Test method: '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Element found with locator: " + locator + " and locatorType: " + locatorType) except: self.log_base.error("[ERROR] Test method: '{0}{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Element not found with locator: " +locator + " and locatorType: " + locatorType +" ###Exception: {}".format(NoSuchElementException)) return element def get_element_list(self, locator, locatorType="id"):""" This method is useful for fetching multiple elements from parent element ======================================================================== Parameter: ---------- 1. Required: 1. locator 2. locatorType Return: ------- It returns list of elements Exception: ---------- Element list NOT FOUND error """ locatorType = locatorType.lower() byType = self.get_by_type(locatorType) elements = self.driver.find_elements(byType, locator) if len(elements) > 0: self.log_base.info("[PASS] Test method: '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Element list FOUND with locator: " + locator + " and locatorType: " + locatorType) else: self.log_base.info("[FAIL] Test method: '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Element list NOT FOUND with locator: " + locator + " and locatorType: " + locatorType) return elements def get_element_type(self, locator, locatorType): """ This method will return type of an element. =========================================== Parameter: ---------- 1. Required 1. locator 2. locatorType Return: ------- It returns element_type. Exception: ---------- None """ element = self.get_element(locator, locatorType) element_type = element.get_attribute("type") if element_type == 'text': return element_type if element_type == 'radio': return element_type if element_type == 'checkbox': return element_type if element_type == 'submit': return element_type def driver_close(self): """Driver instance will be closed :return: It doesn't return anything """ self.driver.close() self.log_base.info("[PASS] Driver is successfully closed using test method:"'{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name)) def sendKeys(self, data, locator, locatorType="id", element=None): """ Send keys to an element -> MODIFIED Either provide element or a combination of locator and locatorType """ try: if locator: # This means if locator is not empty element = self.get_element(locator, locatorType) element.send_keys(data) self.log_base.info("[PASS] Sent data '{0}' on element with locator: ".format(data) + locator + " locatorType: " + locatorType + "using test method '{0}-->{1}'" format(__name__, inspect.currentframe().f_code.co_name)) except: self.log_base.error("[FAIL] Cannot send data '{0}' on the element with locator: ".format(data) + locator + " locatorType: " + locatorType + "using test method ""'{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name))
print_stack() def element_click(self, locator, locatorType="id", element=None): """ Click on an element -> MODIFIED Either provide element or a combination of locator and locatorType """ try: if locator: # This means if locator is not empty element = self.get_element(locator, locatorType) element.click() self.log_base.info("[PASS] Clicked on element with locator: " + locator + " locatorType: " + locatorType + "using test method '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name)) except: self.log_base.error("[FAIL] Cannot click on the element with locator: " + locator + " locatorType: " + locatorType + "using test method '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name)) print_stack() def capture_screenshot(self, resultMessage): """ Takes screenshot of the current open web page """ now = datetime.now() fileName = resultMessage + "." + \ str(now.strftime("%Y%m%d%H:%M:%S %p")) + ".png"screenshotDirectory = "/Users/pravin.a/my-project/venv/MyFramework/screenshots/{0}{1}{2}".format("screenshots", "_", str(now.strftime("%Y%m%d"))) relativeFileName = fileName currentDirectory = os.path.dirname(__file__) destinationFile = os.path.join(screenshotDirectory, relativeFileName) destinationDirectory = os.path.join( currentDirectory, screenshotDirectory) try: if not os.path.exists(destinationDirectory): os.makedirs(destinationDirectory) self.driver.save_screenshot(destinationFile) self.log_base.info("[PASS] Test method: '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + ":" + " Screenshot save to directory:"+ destinationFile) except: self.log_base.error("[FAIL] Test method: '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "### Exception Occurred when taking screenshot") print_stack() def get_title(self): """ This method returns title of the current page. """ return self.driver.title def clear_field(self, locator, locatorType="id"): """ This method will Clear an element field. """ element = self.get_element(locator, locatorType) element.clear() self.log_base.info("[PASS] Test method: '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Clear field with locator: " +locator +" locatorType: " + locatorType) def get_text(self, locator, locatorType="id", element=None, info=""): """ NEW METHOD Get 'Text' on an element Either provide element or a combination of locator and locatorType """ try: if locator: # This means if locator is not empty element = self.get_element(locator, locatorType) text = element.text if len(text) == 0: text = element.get_attribute("innerText") if len(text) != 0: self.log_base.info("[PASS] Test method: '{0}{1}'".format( __name__, inspect.currentframe().f_code.co_name) + "Getting text on element ::"+ info) self.log_base.info("The text is :: '" + text + "'") text = text.strip() except: self.log_base.error("[FAIL] Test method: '{0}{1}'".format( __name__, inspect.currentframe().f_code.co_name) + "Failed to get text on element"+ info) print_stack() text = None return text def is_element_present(self, locator, locatorType="id", element=None): """ Check if element is present -> MODIFIED Either provide element or a combination of locator and locatorType """ try: if locator: # This means if locator is not empty element = self.get_element(locator, locatorType) if element is not None: self.log_base.info("[PASS] Test Method: '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Element present with locator: "+ locator +" locatorType: " + locatorType) return True else: self.log_base.error("[FAIL] Test method: '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Element not present with locator: "+ locator +" locatorType: " + locatorType) return False except: print("[FAIL] Test method: '{0}-->{1}'".format(__name__, inspect.currentframe() .f_code.co_name) + "Element not found" + "###Exception-->{}".format (NoSuchElementException)) return False def is_element_displayed(self, locator, locatorType="id", element=None): """ NEW METHOD Check if element is displayed Either provide element or a combination of locator and locatorType """ isDisplayed = False try: if locator: # This means if locator is not empty element = self.get_element(locator, locatorType) if element is not None: isDisplayed = element.isDisplayed() self.log_base.info("[PASS] Test method: '{0}-->{1}'".format( __name__, inspect.currentframe().f_code.co_name) + "Element is displayed") else: self.log_base.info("[FAIL] Test method: '{0}-->{1}'".format( __name__, inspect.currentframe().f_code.co_name) + "Element is not displayed") return isDisplayed except: print("[ERROR] Test method: '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Element not found" + "###Exception-->{}".format(ElementNotVisibleException)) return False def wait_for_element(self, locator, locatorType="id", timeout=10, pollFrequency=0.5): """ This method will make webdriver to wait for a particular amount of time. """ element = None try: byType = self.get_by_type(locatorType) self.log_base.info("Waiting for maximum :: " + str(timeout) + " :: seconds for element to be clickable") wait = WebDriverWait(self.driver, timeout=timeout, poll_frequency=pollFrequency, ignored_exceptions=[NoSuchElementException, ElementNotVisibleException, ElementNotSelectableException]) element = wait.until(EC.element_to_be_clickable((byType, locator))) self.log_base.info("[PASS] Test method '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Element appeared on the web page" + "with locator" + locator + "and locatortype" + locatorType) except: self.log_base.info("[FAIL] Test method '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Element not appeared on the web page"+ "with locator" + locator + "and locatortype" + locatorType) print_stack() return element def element_presence_check(self, locator, byType): """ Check if element is present ============================= Parameter: ---------- Required: 1. locator 2. byType Return: ------- If element present --> Returns True If element absent --> Returns False Exception: ---------- NoSuchElementException """ try: elementList = self.driver.find_elements(byType, locator) if len(elementList) > 0: self.log_base.info("[PASS] Test method '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Element present with locator: "+ locator +" locatorType: " + str(byType)) return True else: self.log_base.info("[FAIL] Test method '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Element not present with locator: "+ locator +" locatorType: " + str(byType)) return False except: self.log_base.info("[ERROR] Test method: '{0}-->{1}'".format(__name__, inspect.currentframe().f_code.co_name) + "Element not found," +"###Exception-->{}".format(NoSuchElementException)) return False def web_scroll(self, direction="up"): """ NEW METHOD """ if direction == "up": # Scroll Up self.driver.execute_script("window.scrollBy(0, -800);") if direction == "down": # Scroll Down self.driver.execute_script("window.scrollBy(0, 600);") def switch_to_frame(self, id="", name="", index=None): """ Switch to iframe using element locator inside iframe Parameters: 1. Required: Either id, name or index Returns: None Exception: None """if id: self.driver.switch_to.frame(id) self.log_base.info("Test Method: '{0}{1}'".format(__class__, inspect.currentframe( ).f_code.co_name) + "Controll is switched to frame with id: '{}'".format(id)) elif name: self.driver.switch_to.frame(name) self.log_base.info("Test Method: '{0}{1}'".format(__class__, inspect.currentframe( ).f_code.co_name) + "Controll is switched to frame with name: '{}'".format(name)) else: self.driver.switch_to.frame(index) self.log_base.info("Test Method: '{0}{1}'".format(__class__, inspect.currentframe( ).f_code.co_name) + "Controll is switched to frame with index '{}'".format(index)) def switch_to_window(self): parent_handle = self.driver.current_window_handle all_handles = self.driver.window_handles try: for handle in all_handles: if handle not in parent_handle: self.driver.switch_to.window(handle) self.log_base.info("Test Method: '{0}{1}'".format(__class__, inspect.currentframe( ).f_code.co_name) + "switched to a new window '{}'".format(handle)) except: self.log_base.error("Test Method: '{0}{1}'".format(__class__, inspect.currentframe( ).f_code.co_name) + "Invalid window handle, control can't be switched to the "handle:") return parent_handle def switch_to_default_content(self, parent_handle): """ Switch to default content Parameters: 1. Required:1. parent_handle Returns: None Exception: None """ self.driver.switch_to.window(parent_handle) #self.driver.switch_to_default_content()self.log_base.info("Test Method '{}{}'".format(__class__, inspect.currentframe( ).f_code.co_name) + "Control is switched back to default content") def alert_popups(self, choice): alert_popup = self.driver.switch_to.alert if choice in ['ok', 'Ok', 'OK']: alert_popup.accept() elif choice in ['cancel', 'Cancel', 'CANCEL']: alert_popup.dismiss() else: self.log_base.error("Test Method '{}{}'".format(__class__, inspect.currentframe( ).f_code.co_name) + " " + "Invalid choice") def get_element_attribute_value(self, attribute, locator="", locatorType="", element=None):
""" Get value of the attribute of element Parameters: 1. Required: 1. attribute - attribute whose value to find 2. Optional: 1. element - Element whose attribute need to find 2. locator - Locator of the element 3. locatorType - Locator Type to find the element Returns: Value of the attribute Exception: None """ if locator: element = self.get_element( locator=locator, locatorType=locatorType) value = element.get_attribute(attribute) if value is not None: self.log_base.info("Test Method '{0}{1}'".format(__class__, inspect.currentframe( ).f_code.co_name) + "Attribute value is: {} ".format(value)) else: self.log_base.warn("Test Method '{0}{1}'".format(__class__, inspect.currentframe( ).f_code.co_name) + "Attribute value is not returned" + "Make sure an element youare looking for is a valid element") return value def is_enabled(self, locator, locatortype="id", info=""): """ Check if element is enabled Parameters: 1. Required: 1. locator - Locator of the element to check 2. Optional: 1. locatorType - Type of the locator(id(default), xpath, css, className, linkText) 2. info - Information about the element, label/name of the element Returns: boolean Exception: None """ element = self.get_element(locator, locatorType=locatortype) enabled = False try: attributeValue = self.get_element_attribute_value( element=element, attribute="disabled") if attributeValue is not None: enabled = element.is_enabled() else: value = self.get_element_attribute_value( element=element, attribute="class") self.log_base.info( "Attribute value From Application Web UI --> :: " + value) enabled = not ("disabled" in value) if enabled: self.log_base.info("Element :: '" + info + "' is enabled") else: self.log_base.info("Element :: '" + info + "' is not enabled") except: self.log_base.error("Element :: '" + info + "' state could not be found") return enabled def select_option(self, locator, locatorType="id", index=None, text=None, value=None, element=None): """ This method will select an required option/item/element from select element. Parameters: 1. Required: 1. locator 2. locatorType 3. Either index Or text Or value 2. Optional: 1. element Returns: It doesn't return anything Exception: None """ if locator: element = self.get_element(locator, locatorType=locatorType) select = Select(element) if index is not None: select.select_by_index(index) self.log_base.info('Test Method:"{0}{1}"'.format(__class__, inspect.currentframe ().f_code.co_name) + "is successful. " + "Element is selected successfully") elif text is not None: select.select_by_visible_text(text) self.log_base.info('Test Method:"{0}{1}"'.format(__class__, inspect.currentframe ().f_code.co_name) + "is successful. " + "Element '{}' is selected successfully".format(text)) elif value is not None: select.select_by_value(value) self.log_base.info('Test Method:"{0}{1}"'.format(__class__, inspect.currentframe ().f_code.co_name) + "is successful. " + "Element '{}' is selected successfully". format(value)) else: print("Invalid argument to select method") self.log_base.error("Test method: '{0}{1}'".format(__class__, inspect.currentframe ().f_code.co_name) + "is failed. " + "Unable to select an item" + "'{}'". format('"Invalid argument to select method"')) def deselect_all(self, locator, locatorType): """ This method will deselect all the selected items/options from the select element. Parameter: 1. Required: 1. locator 2 locatorType 2. Optional: None Return: element [*Note - This is optional] Exception: None """ element = self.get_element(locator, locatorType=locatorType) select = Select(element) select.deselect_all() self.log_base.info("Test Method '{0}{1}'".format( __class__, inspect.currentframe().f_code.co_name) + "Elements are deselected") return element def get_all_selected_options(self, locator, locatorType): element = self.get_element(locator, locatorType=locatorType) select = Select(element) allSelectedOptions = select.all_selected_options return allSelectedOptions, element def get_all_options(self, locator="", locatorType="id", element=None): """ This method will find out and return all the options from Select element. Parameter: 1. Required: 1. locator 2 locatorType 2. Optional: 1. element Return: None Exception: None """ if locator: element = self.get_element(locator, locatorType=locatorType) select = Select(element) options = select.options return options if element: select = Select(element) options = select.options return options def drag_and_drop(self, source, target): """ This method will drag the source element to a target/destination element. Parameter: 1. Required: 1. source - source from which files are required to be copied. 2. target - target at which files needs to be copied. 2. Optional: None Return: None Exception: None """ action_chains = ActionChains(self.driver) # Disable below line of code if doesn't work. action_chains.drag_and_drop(source, target).perform() # Enable below line of code if above code doesn't work. action_chains.click_and_hold(source).release(target).perform() def file_upload(self, locator, locatorType, file_path, element=None): """ This method will upload the required file at the desired location. Parameter: 1. Required: 1. locator 2. locatorType 3. file_path 2. Optional: 1. element Return: None Exception: None """ if locator: element = self.get_element( locator=locator, locatorType=locatorType) element.send_keys(file_path) else: self.sendKeys(data=file_path, element=element, locator="") def get_data_web_table(self, locator, locatorType="id", element=None): """ :param locator: locator to find out an element :param locatorType: default locator type is 'id' :param element: By default element is set to None and it will be set to the value as passed through the script. :return: It returns a list of cell values from the web table """ web_table_list = [] if locator: table = self.get_element(locator, locatorType) element = table for row in element.find_elements(By.XPATH, ".//tr"): for cell in row.find_elements(By.XPATH, './/td'): web_table_list.append(cell.text) return web_table_list
=================================================================================
Similarly, you can create generic methods for your UI to be tested under this base class.
Comments
Post a Comment