简体   繁体   中英

Data driven tests. reading parameters from a .json or .yaml file using Selenium Python

I create a framework using Selenium and Python. My data driven framework consists of 2 files so far: The 1st file- Setup.py contains class Actions() that consist of all possible functions that I will use in my framework, such as:

def __init__(): 
def setup():
def tearDown():
def click():
def sendKeys():

My click and sendKeys functions have a minimum of 2 parameters. They take the first parameter such us :id_for_element , xp_for_element , or css_for_element , slicing words until they get the 1st two characters and find element by either id, xp or any other way. Then they use the 2nd parameter to specify an element's value, and 3rd parameter to specify a value for send_keys() function. All of these functions are now working, but so far value hardcoded in my test file.

setup.py file :

from   selenium import webdriver
from   selenium.webdriver.common.by import By
from   selenium.webdriver.common.keys import Keys
from   selenium.webdriver.support.ui import Select
from   selenium.common.exceptions import NoSuchElementException
from   selenium.common.exceptions import NoAlertPresentException

class Actions(object):

    def __init__(self,driver=None):
        if driver != None:
            self.driver = driver

    def setUp(self, browserName):
        if browserName == 'Chrome':
            self.driver = webdriver.Chrome()
            self.driver.delete_all_cookies()
            self.driver.maximize_window()
        elif browserName == 'Safari':
            self.driver = webdriver.Safari()
            self.driver.delete_all_cookies()
            self.driver.maximize_window()
        elif browserName == 'Firefox':
            self.driver = webdriver.Firefox()
            self.driver.delete_all_cookies()
            self.driver.maximize_window()
        self.driver.implicitly_wait(30)

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

    def webPage(self):
        self.driver.get('https://www.yahoo.com')

    def click(self, elemLocator, elemValue):
        elp = elemLocator
        flp = slice(0,2)
        if elp[flp] == 'id':#return by ID
            try:
                self.driver.find_element_by_id(elemValue).click()
            except:
                pass
        elif elp[flp] == 'xp':#return by XPATH
            try:
                self.driver.find_element_by_xpath(elemValue).click()
            except:
                pass


    def sendKeys(self, elemLocator, elemValue, messageValue):
        elp = elemLocator
        flp = slice(0,2)
        if elp[flp] == 'id':#return by ID
            try:
                self.driver.find_element_by_id(elemValue).click()
                self.driver.find_element_by_id(elemValue).clear()
                self.driver.find_element_by_id(elemValue).send_keys(messageValue)
            except:
                pass

        elif elp[flp] == 'xp':#return by XPATH
            try:
                self.driver.find_element_by_xpath(elemValue).click()
                self.driver.find_element_by_xpath(elemValue).clear()
                self.driver.find_element_by_xpath(elemValue).send_keys(messageValue)
            except:
                pass

#test.py file

    from Setup import Actions

class test_case_1: #find element by id

    action = Actions(object)
    action.setUp('Chrome')
    action.webPage()
    action.click('id_of_yahoo_logo', 'uh-logo')
    action.tearDown('Chrome')


class test_case_2: #find element by xpath

    action = Actions(object)
    action.setUp('Chrome')
    action.webPage()
    action.click('xp_of signIn_button', '//*[@id="uh-signin"]')
    action.tearDown('Chrome')

class test_case_3: #login to email

    action = Actions(object)
    action.setUp('Chrome')
    action.webPage()
    action.click('xp_of signIn_button', '//*[@id="uh-signin"]')
    action.sendKeys('id_username_login_inp_field','login-username','deniska')
    action.click('id_of submit_button', 'login-signin')
    action.tearDown('Chrome')

Instead I am trying to pass value for parameters from another file as described by the best practices for data driven testing framework. My next step is to create a data.json file that I will use to map out all elements of the DOM in the following format: "id_login_button":"some id value", "xp_input_field":"some xp value" etc. Can someone, please, help me figure out how to implement this technique?

Here is the simple approach if you want to use the json as your uiRepo.

sample.json:

{
    "id_of_yahoo_logo":"uh-logo",
    "xp_of_signIn_button":"//*[@id='uh-signin']",
    "id_username_login_inp_field":"New York",
    "id_of_submit_button":"login-signin"
}

test.py

# you have to just specify the name as shown below
action.click('xp_of_signIn_button)

Reading value in Actions.py:

import json

#parse json
with open('sample.json') as f:
    uiRepo = json.load(f)

# update the generic methods to get the property form json
print(uiRepo['id_of_yahoo_logo'])

Edit 1:setup.py Un-Tested updates

from   selenium import webdriver
from   selenium.webdriver.common.by import By
from   selenium.webdriver.common.keys import Keys
from   selenium.webdriver.support.ui import Select
from   selenium.common.exceptions import NoSuchElementException
from   selenium.common.exceptions import NoAlertPresentException
import json

class Actions(object):
    # initialize uiRepo
    uiRepo = None
    def __init__(self,driver=None):
        if driver != None:
            self.driver = driver
            # load the uiRepo from json when you init the driver
            with open('sample.json') as repo:
                uiRepo = json.load(repo)

    def setUp(self, browserName):
        browserName = browserName.lower()
        if browserName == 'chrome':
            self.driver = webdriver.Chrome()
        elif browserName == 'safari':
            self.driver = webdriver.Safari()
        elif browserName == 'firefox':
            self.driver = webdriver.Firefox()
        self.driver.delete_all_cookies() #< === moved this line
        self.driver.maximize_window() #< === moved this line
        self.driver.implicitly_wait(30)

    def tearDown(self): #< === Removed browser here as you don't need browser name while closing it.
        self.driver.quit()

    def webPage(self,url): #< === Added url as param, rather hard code
        self.driver.get(url)

    # new method to get the element based on the jsonKey
    def getElement(self, jsonKey):
        locatorStrategy = jsonKey[:2]  # <=== getting first 2 chars to figure out if it's id/xp
        locator = uiRepo[jsonKey]  # < == getting value from json
        ele = None
        try:
            if locatorStrategy == 'id':  # return by ID
                ele =  self.driver.find_element_by_id(locator).click()  # <=== using the locator got from json
            elif locatorStrategy == 'xp':  # return by XPATH
                ele =  self.driver.find_element_by_xpath(locator).click()
        except:
            pass
        # if you want you can add additional logic something like highlighting the element
        return ele

    def click(self, jsonKey): # < ==== updated method to accept only jsonElementName (Removed the element value param)
        ele = self.findElement(jsonKey)
        ele.click()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM