# Python selenium object repository

I was trying to create the selenium web element object repository in python. I have come up with three ways to do so. However, I am new to python so I am not sure which one is better than other.

Note: I am using Page object pattern for writing my tests, however just for understanding and simplicity I have put all the function in one file (class).

First: Using Decorator

def FindBy(by, value):
def decorator(func):
def wrapper(self):
return self.driver.find_element(by, value)
return wrapper
return decorator

@FindBy(By.NAME, "q")
def search_input(self): pass

def test_search(self):
self.driver = webdriver.Firefox()
self.search_input().send_keys("selenium python")


Second & Third: using Lambda and Method

class TestGoogle(object):

def find_element(self, by, value):
return self.driver.find_element(by, value)

def search_input(self): return self.find_element(By.NAME, "q")

search_input_1 = lambda self: self.find_element(By.NAME, "q")

def test_search(self):
self.driver = webdriver.Firefox()
self.search_input().send_keys("selenium python")
self.search_input_1().clear()


If I were to use "find by" PageFactory-like notation in Python, I would go with the one proposed here - similar to your versions, but more concise and supports more features:

from pageobject_support import callable_find_by as find_by

search_input = find_by(how=By.NAME, using='q')


Old Answer (in case there is anything useful there)

I would go further and follow the Page Object pattern, creating abstractions for the pages and elements you are working with, as demonstrated in the selenium documentation. This way you are isolating your locators from the logic of the test providing an "API" to work with a particular page.

Here is one way to do it - pay attention to how simple and concise the actual test has become:

import unittest

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

class MainPageLocators(object):
"""A class for main page locators. All main page locators should come here"""
SEARCH_INPUT = (By.NAME, 'q')

class BasePage(object):
"""Base class to initialize the base page that will be called from all pages"""

def __init__(self, driver):
self.driver = driver

class MainPage(BasePage):

def search(self, search_query):
"""Triggers the search"""
search_input = self.driver.find_element(*MainPageLocators.SEARCH_INPUT)
search_input.send_keys(search_query)
search_input.send_keys(Keys.ENTER)

def setUp(self):
self.driver = webdriver.Firefox()

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

def test_search(self):
main_page = MainPage(self.driver)
main_page.search("selenium python")


Note that you may also want a separate class for an element, but this should be good enough to get you started.

Also note that I'm using a unittest.TestCase as a base class for your test which, aside from bringing other benefits, allows to nicely start and close a browser via setUp and tearDown.

• I am also using the page object patter. however this is just for the self.driver.find_element(*MainPageLocators.SEARCH_INPUT) syntax, similar to how we do in PageFactory in Java – Gaurang Shah Aug 24 '17 at 13:21
• @GaurangShah gotcha, updated the answer a bit. Check it out, thanks. – alecxe Aug 24 '17 at 13:36