Collection of test helpers, specifically for Selenium Webdriver functional tests
This project is maintained by aychedee
A collection of tools to help when functional testing
It contains utilities that assist with tasks like running a browser in a headless environment, or checking that emails have been sent, or a file has been uploaded to a server, or common testing flow control like retrying or ignoring certain errors.
Keteparaha is available on PyPi. To install the latest release simply run:
pip install keteparaha
BrowserTestCase is a sub classed unittest.TestCase designed to make working with Selenium Webdriver simpler. It can operate in headless mode to be used with continuous integration.
Page and Component represent a web app's pages, or the components that can be found on those pages.
from keteparaha import BrowserTestCase, Component, Page
SERVER_URL = 'http://www.simple.com/{}'
# Pages are identified by their full URL with any GET parameters
# stripped off
class LoginPage(Page):
url = SERVER_URL.format('login/')
def login(self, email, password):
self.enter_text('input[name=email]', email)
self.enter_text('input[name=password]', email)
return self.click('input[name=submut]')
class Dashboard(Page):
url = SERVER_URL.format('dashboard/')
def logged_in_username(self):
return self.get_component('.username').text
def open_comment_modal(self, comment):
return self.click_button('Feedback', opens='#comment')
class CommentModal(Component)
selector = '#comment'
def comment(self, message):
self.enter_text('input[name=message]', message)
self.click('input[type=submit]')
# User logs in and is redirected to the dashboard
dashboard = LoginPage(self.driver).login('a@b.com', 'xxxxx')
# Their username is in the top menu
self.assertEqual(dashboard.logged_in_username(), 'aychedee')
# They can leave some feedback for the site owner
comment_modal = dashboard.open_comment_modal()
comment_modal.comment("Is it tea you're looking for?")
Keteparaha is released under the MIT license, see LICENSE in the software repository for more details. Copyright 2015 by Hansel Dunlop.
def ignore(
func, errors)
Ignore exceptions given in errors
def retry(
func, errors, attempts=5)
Retry the action if an exception occurs
def snapshot_on_error(
method)
A decorator that captures a snapshot of all browsers on error
By default these are saved in the home directory, to change the snapshot location set SNAPSHOT_PATH on the test case. The snapshot directory will be created if possible.
class BrowserTestCase
Browser test case that can be used with Selenium Webdriver to functionally test a website
var browser
Returns the last browser started
var browsers
def __init__(
self, *args, **kwargs)
def is_headless(
self)
Used to determine if the test is running in a headless env
def run(
self, result=None)
def start_browser(
self, size=(1300, 1080), driver='Firefox')
Start and return a Selenium Webdriver browser instance
class Component
Generic page component, intended to be subclassed
Pages and Components are stored in a registry and switched to dynamically
class ShoppingBasket(Component): selector = '#shopping-basket'
def remove_item(self, name):
contents = self.get_components('tr')
for item in contents:
if name in item.text:
item.click('.remove')
return
raise AssertionError('No item in basket called "{0}"'.format(name))
page = Page(driver) basket = page.click_link('Shopping Basket', opens=ShoppingBasket)
basket.remove_item('Buzz Lightyear')
var ComponentMissing
var TimeoutException
var selector
var page
var text
The visible text of the component
var url
The url of the page which the component is inside
def __init__(
self, parent, driver=None, find_by=u'selector')
def clear(
self, selector)
Clear text out of input identified by CSS selector
def click(
self, selector=None, opens=None)
Main method for interacting with a page or component
Returns either self, a new page object based on browser url, or a page component based on the selector passed in as 'opens'. selector can be a css selector in the form of a string, or a selenium WebElement.
def click_button(
self, button_text, opens=None)
Find buttons on the page and click the first one with the text
def click_link(
self, link_text, opens=None)
def enter_text(
self, selector, text)
Enter text into DOM element identified by selector
The function performs some error checking because as of Jan 2014 send_keys on the element is unreliable at text entry.
def get_attribute(
self, attribute)
Return the value of an attribute of the component
def get_clickable_element(
self, selector, driver=None)
Return an element that can be clicked, or raise an error
def get_component(
self, component_or_selector)
Return an initialised component present in page
takes either a component class to find in the page or a css selector.
If the selector is not present in the page raises a ComponentMissing error.
def get_components(
self, component_or_selector)
Return an list of initialised components present in page
Returns an empty list if no components could be found
def get_element(
self, selector, driver=None)
Get the DOM element identified by the css selector
def get_element_by_link_text(
self, link_text)
Get the DOM element identified by the css selector
def get_elements(
self, selector)
Get a list of elements identified by the css selector
def get_visible_element(
self, selector)
Return an element that is visible, or raise an error
def has_text(
self, text)
Return whether the text is in the component
def hover(
self, selector, opens=None)
Hover over element identified by CSS selector
def location(
self)
The current page location without any query parameters
def scroll_into_view(
self)
Scroll the window until the component is visible
def select_option(
self, selector, option_text)
Select option in dropdown identified by selector with given text
def text_in_element(
self, selector, text)
Return whether the text is in the element identified by selector
def wait_for_invisibility(
self, selector)
Pause until the element identified by selector is invisible
class GmailImapClient
Imap client with some specific methods for working with gmail
var IMAP_SERVER
var IMAP_SERVER_PORT
var client
var email_address
var messages_for_this_session
var password
def __init__(
self, email_address, password)
def delete_seen_messages(
self)
Delete messages that have been accessed with this client
def emails_from_messages(
self, messages)
Convert a list of IMAP messages into email objects
def gmail_search(
self, query)
Search the gmail imap server using gmail queries
def search(
self, from_address, to_address, subject, since=datetime.datetime(2015, 3, 26, 8, 30, 10, 560983))
Search for emails on an IMAP server
class HeadlessBrowserTestCase
Seleniun Webdiver test case for headless environemnts
Browser test case that will start a virtual display to run the Webdriver browser in before running test cases
def is_headless(
self)
Inheritance:
BrowserTestCase
.is_headless
Used to determine if the test is running in a headless env
def start_browser(
self, size=(1300, 1080), driver='Firefox', **kwargs)
Inheritance:
BrowserTestCase
.start_browser
Start xvfb headless display and a browser inside it
Extra keyword args are passed directly to the XvFB interface
class Page
Generic web page, intended to be subclassed
Pages and Components are stored in a registry and switched to dynamically
class LoginPage(Page): url = 'https://your-site.com/login
def login(username, password):
self.enter_text("input[name=username]", username)
self.enter_text("input[name=password]", password)
return self.click("input[type=submit]")
var ComponentMissing
var TimeoutException
var page
Unifies the api for pages and components slightly
var selector
var text
The visible text of the component
def __init__(
self, driver=None)
def clear(
self, selector)
Clear text out of input identified by CSS selector
def click(
self, selector=None, opens=None)
Main method for interacting with a page or component
Returns either self, a new page object based on browser url, or a page component based on the selector passed in as 'opens'. selector can be a css selector in the form of a string, or a selenium WebElement.
def click_button(
self, button_text, opens=None)
Find buttons on the page and click the first one with the text
def click_link(
self, link_text, opens=None)
def enter_text(
self, selector, text)
Enter text into DOM element identified by selector
The function performs some error checking because as of Jan 2014 send_keys on the element is unreliable at text entry.
def get_attribute(
self, attribute)
Return the value of an attribute of the component
def get_clickable_element(
self, selector, driver=None)
Return an element that can be clicked, or raise an error
def get_component(
self, component_or_selector)
Return an initialised component present in page
takes either a component class to find in the page or a css selector.
If the selector is not present in the page raises a ComponentMissing error.
def get_components(
self, component_or_selector)
Return an list of initialised components present in page
Returns an empty list if no components could be found
def get_element(
self, selector, driver=None)
Get the DOM element identified by the css selector
def get_element_by_link_text(
self, link_text)
Get the DOM element identified by the css selector
def get_elements(
self, selector)
Get a list of elements identified by the css selector
def get_visible_element(
self, selector)
Return an element that is visible, or raise an error
def has_text(
self, text)
Return whether the text is in the component
def hover(
self, selector, opens=None)
Hover over element identified by CSS selector
def location(
self)
The current page location without any query parameters
def scroll_into_view(
self)
Scroll the window until the component is visible
def select_option(
self, selector, option_text)
Select option in dropdown identified by selector with given text
def text_in_element(
self, selector, text)
Return whether the text is in the element identified by selector
def wait_for_invisibility(
self, selector)
Pause until the element identified by selector is invisible