Python Selenium
A concise tutorial to a concise language
Prakat Solutions
16th July 2016
Contents
-
A simple website setup
-
Selenium bindings for Python
-
Simple example
-
Using selenium to write tests
-
Navigating through pages
-
Locating elements on a page
-
Waits
-
Page Objects in Selenium
-
Web Driver API
-
Firefox & Chrome Driver APIs - differences
-
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
- title_is
- title_contains
- visibility_of
- presence_of_all_elements_located
- text_to_be_present_in_element
- text_to_be_present_in_element_value
- frame_to_be_available_and_switch_to_it
- invisibility_of_element_located
- element_to_be_clickable - it is Displayed and Enabled.
- element_located_selection_state_to_be
- 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()
- click(on_element)
- click_and_hold(on_element)
- 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"
- authenticate(username, password)
- send_keys(keysToSend)
- 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
By Abhiram Ravikumar
Python Selenium
Third lecture in the python selenium workshop series
- 3,722