Python Selenium

A concise tutorial to a concise language

4CCON | Chennai

Jan 26 2016

Contents

  1. A simple website setup 

  2. Selenium bindings for Python

  3. Simple example

  4. Using selenium to write tests

  5. Navigating through pages

  6. Locating elements on a page

  7. Waits

  8. Page Objects in Selenium

  9. Web Driver API

  10. Firefox & Chrome Driver APIs - differences

  11. Best practices & wrap up

Selenium bindings for Python

  • Web UI Automation means the automatic execution of the actions performed in a web browser window
  • Selenium WebDriver is the one that can automate all these tasks.
  • Instead of Java, we are using Python.
+
++

Selenium bindings for Python

  • Installing Selenium
  • Simple test script
pip install -U selenium
pip install selenium --upgrade



#test script

from selenium import webdriver

browser = webdriver.Firefox()
browser.get('http://seleniumhq.org/')

A Simple Example

  • Open a browser instance
  • Load a website
  • Perform actions using the functions provided
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

driver = webdriver.Firefox()
driver.get("http://www.python.org")
assert "Python" in driver.title
elem = driver.find_element_by_name("q")
elem.clear()
elem.send_keys("pycon")
elem.send_keys(Keys.RETURN)
assert "No results found." not in driver.page_source
driver.close()

Writing tests with Selenium

  • Write test cases using Python’s unittest module - a framework for organizing the test cases
  • unittest module is based on Java's JUnit
  • The setUp method-  initialization
  • tearDown method - cleanup actions
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

class PythonOrgSearch(unittest.TestCase):

    #initializing the framework
    def setUp(self):
        self.driver = webdriver.Firefox()
    
    #test case definition
    def test_search_in_python_org(self):
        driver = self.driver
        driver.get("http://www.python.org")
        self.assertIn("Python", driver.title)
        elem = driver.find_element_by_name("q")
        elem.send_keys("pycon")
        elem.send_keys(Keys.RETURN)
        assert "No results found." not in driver.page_source

    # any clean up work
    def tearDown(self):
        self.driver.close()

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

Navigating through pages

  • Finding an element on a page
  • Interacting with the element
<input type="text" name="passwd" id="passwd-id" />

#Finding an element
element = driver.find_element_by_id("passwd-id")
element = driver.find_element_by_name("passwd")
element = driver.find_element_by_xpath("//input[@id='passwd-id']")

#Interacting with the element
element.send_keys("some text")
element.send_keys(" and some", Keys.ARROW_DOWN)



Page interaction

Navigating through pages

  • Selecting and deselecting options
  • Default selected options
  • All options
  • Submitting a form 
from selenium.webdriver.support.ui import Select

#selecting options
select = Select(driver.find_element_by_name('name'))
select.select_by_index(index)
select.select_by_visible_text("text")
select.select_by_value(value)

#deselecting options
select = Select(driver.find_element_by_id('id'))
select.deselect_all()

#default selected options
select = Select(driver.find_element_by_xpath("xpath"))
all_selected_options = select.all_selected_options

#all options
options = select.options

#Submitting
driver.find_element_by_id("submit").click()

Filling in forms

Navigating through pages

  • Select the source and destination element
  • Drag and drop using action_chains
element = driver.find_element_by_name("source")
target = driver.find_element_by_name("target")

from selenium.webdriver import ActionChains
action_chains = ActionChains(driver)
action_chains.drag_and_drop(element, target).perform()

Drag and drop

Navigating through pages

  • Switching between windows
  • Switching between frames
#Switch a window
#find window name from javascript that called it
#<a href="somewhere.html" target="windowName">Click here to open a new window</a>
driver.switch_to_window("windowName")

#Switching to frames
driver.switch_to_frame("frameName")

#Accessing subframes
driver.switch_to_frame("frameName.0.child")

Switching windows and frames

Locating elements

  • Uses the id tag to locate elements in a page
  • Each element has a unique id
'''<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
  </form>
 </body>
<html> '''

login_form = driver.find_element_by_id('loginForm')

Locating by id

Locating elements

  • Uses the name tag to locate elements in a page
  • Multiple elements might share a name
'''<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
   <input name="continue" type="button" value="Clear" />
  </form>
 </body>
<html> '''

username = driver.find_element_by_name('username')
password = driver.find_element_by_name('password')

#Returns login
continue = driver.find_element_by_name('continue')

Locating by name

Locating elements

  • Used when you don’t have a suitable id or name attribute for the element
  • Can be used in absolute or relative terms
  • Use the tree structure of html
'''<html>
 <body>
  <form id="loginForm">
   <input name="username" type="text" />
   <input name="password" type="password" />
   <input name="continue" type="submit" value="Login" />
   <input name="continue" type="button" value="Clear" />
  </form>
 </body>
<html> '''

#locate the login form element
login_form = driver.find_element_by_xpath("/html/body/form[1]")
login_form = driver.find_element_by_xpath("//form[1]")
login_form = driver.find_element_by_xpath("//form[@id='loginForm']")

#locate the username element
username = driver.find_element_by_xpath("//form[input/@name='username']")
username = driver.find_element_by_xpath("//form[@id='loginForm']/input[1]")
username = driver.find_element_by_xpath("//input[@name='username']")

Locating by xpath

Locating elements

  • Use the class tag to find elements
'''<html>
 <body>
  <p class="content">Site content goes here.</p>
</body>
<html> '''

#Find by class name
content = driver.find_element_by_class_name('content')

Locating by class

Waits

  • Not all page elements get loaded at the same time
  • Explicit waits
    • time.sleep()
  • Implicit waits
    • driver.implicitly_wait()
try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "myDynamicElement"))
    )
finally:
    driver.quit()

Waits - Implicit

  • Polls the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available.
from selenium import webdriver

driver = webdriver.Firefox()
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")

Waits - Conditions

  1. title_is
  2. title_contains
  3. visibility_of
  4. presence_of_all_elements_located
  5. text_to_be_present_in_element
  6. text_to_be_present_in_element_value
  7. frame_to_be_available_and_switch_to_it
  8. invisibility_of_element_located
  9. element_to_be_clickable - it is Displayed and Enabled.
  10. element_located_selection_state_to_be
  11. alert_is_present

Page objects

  • Represents an area in the web application user interface that your test is interacting
  • Why do we use them?
    • reusable code that can be shared across test cases
    • Reducing the amount of duplicated code
    • If the user interface changes, the fix needs changes in only one place

Page object classes

  • Page Object pattern
    • screens of web app as a series of objects
    • allows us to model the UI in our tests
    • A page object is an object-oriented class that serves as an interface to a page
  • Creates objects for each web page
  • Test code & technical implementation well separated

Page elements

  • Page.py
  • Element.py
  • Locators.py

Case study

Web driver API

# suggested import style
from selenium import webdriver

#Accessing classes
webdriver.Firefox
webdriver.FirefoxProfile
webdriver.Chrome
webdriver.ChromeOptions

#keys import
from selenium.webdriver.common.keys import Keys

driver.current_url #no round braces - returns URL
driver.close() #callable 

Web D. API - Exceptions

#When trying to select an unselectable element
selenium.common.exceptions.ElementNotSelectableException(msg=None)
#Example: selecting a ‘script’ element

#When element is present but not visible
selenium.common.exceptions.ElementNotVisibleException(msg=None)
#Example: read text of an element that is hidden from view

#When such an attribute is not found
selenium.common.exceptions.NoSuchAttributeException(msg=None)
#IE8’s .innerText vs. Firefox .textContent)

#When such an element is not found
selenium.common.exceptions.NoSuchElementException()
#Wrong element search  name

Web D. API - Action Chains

#Generate user actions on the mouse

menu = driver.find_element_by_css_selector(".nav")
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")

actions = ActionChains(driver)
actions.move_to_element(menu)
actions.click(hidden_submenu)
actions.perform()
  1. click(on_element)
  2. click_and_hold(on_element)
  3. double_click(on_element)

Web D. API - Alert

#Accept or Dismiss alert
Alert(driver).accept()
Alert(driver).dismiss()

#Accessing the alert
alert = browser.switch_to_alert()
alert.accept()
print "alert accepted"


  1. authenticate(username, password)
  2. send_keys(keysToSend)
  3. alert.text

Firefox v/s Chrome

class selenium.webdriver.firefox.webdriver.WebDriver


quit()
#Quits the driver and close every associated window.

set_context(context)

firefox_profile

class selenium.webdriver.chrome.webdriver.WebDriver

launch_app(id)
#Launches Chrome app specified by id.

create_options()
#different options during creation of chrome window
quit()

Best Practices

  • Figure out what works best for you
  • Page Object design pattern
  • Variables naming convention [ _ and ()]
  • Separating action and intent
  • there is no single 'best' approach
  • agile, iterative, incremental approach
  • keep selenium up to date
  • Practice
  • Hack around

Thank You!

Questions?

Python Selenium 4CCON

By Abhiram Ravikumar

Python Selenium 4CCON

Third lecture in the python selenium workshop series

  • 4,264