Keteparaha

Collection of test helpers, specifically for Selenium Webdriver functional tests

This project is maintained by aychedee

keteparaha module

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.

Installation

Keteparaha is available on PyPi. To install the latest release simply run:

pip install keteparaha

Usage

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?")

License

Keteparaha is released under the MIT license, see LICENSE in the software repository for more details. Copyright 2015 by Hansel Dunlop.

Functions

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.

Classes

class BrowserTestCase

Browser test case that can be used with Selenium Webdriver to functionally test a website

Ancestors (in MRO)

Instance variables

var browser

Returns the last browser started

var browsers

Methods

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)

The following would also work identically:

basket = page.click_link('Shopping Basket', opens='#shopping-basket')

basket.remove_item('Buzz Lightyear')

Ancestors (in MRO)

Class variables

var ComponentMissing

var TimeoutException

var selector

Instance variables

var page

var text

The visible text of the component

var url

The url of the page which the component is inside

Methods

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 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

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

Ancestors (in MRO)

Class variables

var IMAP_SERVER

var IMAP_SERVER_PORT

Instance variables

var client

var email_address

var messages_for_this_session

var password

Methods

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

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

Ancestors (in MRO)

Instance variables

var browser

Inheritance: BrowserTestCase.browser

Returns the last browser started

var browsers

Inheritance: BrowserTestCase.browsers

Methods

def __init__(

self, *args, **kwargs)

Inheritance: BrowserTestCase.__init__

def is_headless(

self)

Inheritance: BrowserTestCase.is_headless

Used to determine if the test is running in a headless env

def run(

self, result=None)

Inheritance: BrowserTestCase.run

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]")

Ancestors (in MRO)

Class variables

var ComponentMissing

var TimeoutException

Instance variables

var page

Unifies the api for pages and components slightly

var selector

var text

The visible text of the component

Methods

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 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

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