Skip to content

Selenium WebDriver: Implementing PageObject in Python

March 18, 2013

Selenium logo

Hi, here is short description of Selenium Webdriver PageObject pattern ( implementation in Python.

First of all let’s create some base classes for further use:

WebDriver wrapper to launch the only instance of driver in the same time:

from selenium import webdriver

class SeleniumWrapper:
  _instance = None

  def __new__(cls, *args, **kwargs):
    if not cls._instance:
      cls._instance = super(SeleniumWrapper, cls).__new__(cls, *args, **kwargs)
    return cls._instance

  def connect(self, host=""):
    self.driver = webdriver.Firefox()
    self.base_url = host
    return self.driver

Base page object and page element classes:

import unittest
import time

class BasePageObject(unittest.TestCase):
def wait_for_element_displayed_by_id(self, driver, locator, timeout=60, msg="[error] element is not found" ):
  for i in range(timeout):
      if driver.find_element_by_id(locator).is_displayed(): break
class BasePageElement(object):
  def __get__(self, obj, cls=None):

  def __delete__(self, obj):

In package where your base classes located you need to put SeleniumWrapper class instance creation into file, e.g.:

from pageobjects.base.seleniumwrapper import SeleniumWrapper
selenium_driver = SeleniumWrapper()

So let’s look at the basic login page, here is pageobject class for it:

from pageobjects import locators
from pageobjects.base import selenium_driver
from pageobjects.base.basepageobject import BasePageObject
from pageobjects.base.basepageelement import BasePageElement

class UsernameElement(BasePageElement):
  def __init__(self):
    self.locator = locators["login.username"]

  def __set__(self, obj, val):
    driver = selenium_driver.driver

class PasswordElement(BasePageElement):
  def __init__(self):
    self.locator = locators["login.password"]

  def __set__(self, instance, value):
    driver = selenium_driver.driver

class LoginPageObject(BasePageObject):
  username = UsernameElement()
  password = PasswordElement()

  def __init__(self, driver, base_url):
    self.driver = driver
    self.wait_for_element_displayed_by_id(self.driver, "id_username")
    self.assertEqual("Login", self.driver.title)

  def submit(self):
    self.wait_for_page_title(self.driver, "Profile", msg="[error]: we are not logged in")

It is good practice to put all elements locators into one place, e.g.:

locators = {}
locators[""] = "login-open"
locators["login.username"] = "id_username"
locators["login.password"] = "id_password"
locators["login.submit"] = "button-login"

What’s next? We need to run tests:

import unittest
from pageobjects.base import selenium_driver
from pageobjects.login.loginpageobject import LoginPageObject
from import AboutPageObject

class AboutPageTests(unittest.TestCase):
  def setUp(self):
    self.verificationErrors = []
    self.driver = selenium_driver.connect()
    self.base_url = selenium_driver.base_url

  def tearDown(self):
    self.assertEqual([], self.verificationErrors)

  def test_login(self):
    lpo = LoginPageObject(self.driver, self.base_url)

    lpo.username = ""
    lpo.password = "pwdpwd123"

if __name__ == "__main__":

Good luck!
P.S.: If you need to run your tests beyond CI (e.g. Jenkins) use Corey Goldberg blog post Python – Headless Selenium WebDriver Tests using PyVirtualDisplay

UPD: Source code on GitHub

  1. pcp permalink

    Actually, here’s now a Python package for implementing the PageObjects design:

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: