Fork me on GitHub

webtest.sel – Functional Testing with Selenium

Routines for testing WSGI applications with selenium.

Most interesting is SeleniumApp and the selenium() decorator

class webtest.sel.SeleniumApp(app=None, url=None, timeout=30000, extra_environ=None, relative_to=None, **kwargs)[source]

See webtest.TestApp

SeleniumApp only support GET requests


The current Selenium


Close selenium and the WSGI server if needed

class webtest.sel.Selenium[source]

Selenium RC control aka browser

A object use to manipulate DOM nodes. This object allow to use the underlying selenium api. See Selenium api

You can use the original method name:

browser.fireEvent('id=#myid", 'focus')

Or a more pythonic name:

browser.fire_event('id=#myid", 'focus')

Both are equal to:

browser.execute('fireEvent', 'id=#myid', 'focus')

A callable usable as:

  • class decorator
  • function decorator
  • contextmanager

Response API

Some of the return values return instances of these classes:

class webtest.sel.TestResponse(body=None, status=None, headerlist=None, app_iter=None, content_type=None, conditional_response=None, **kw)[source]

Expose a Document

follow(status=None, **kw)[source]

If this request is a redirect, follow that redirect. It is an error if this is not a redirect response. Returns another response object.

class webtest.sel.Document(resp)[source]

The browser document. resp.doc.myid is egual to resp.doc.css('#myid')

button(description=None, buttonid=None, index=None)[source]

Get a button


Get an Element using a css selector

get(tag, **kwargs)[source]

Return an element matching tag, an attribute and an index. For example:

resp.doc.get('input', name='go') => xpath=//input[@name="go"]
resp.doc.get('li', description='Item') => xpath=//li[.="Item"]
input(value=None, name=None, inputid=None, index=None)[source]

Get an input field

Get a link


Get an Element using xpath

class webtest.sel.Element(resp, locator)[source]

A object use to manipulate DOM nodes. This object allow to use the underlying selenium api for the specified locator. See Selenium api

You can use the original method name:


Or a more pythonic name:


Both are equal to:

browser.execute('fireEvent', element.locator, 'focus')

Return the attribute value of the element


Drag and drop to element


Eval a javascript expression in Selenium RC. You can use the following variables:

  • s: the selenium object
  • b: the browserbot object
  • l: the element locator string
  • e: the element itself

return true is the element is present


True iif the class is present


Return the innerHTML of the element


Return the text of the element


Wait for an element and return this element


Wait for an element, click on it and return this element

class webtest.sel.Form(resp, id)[source]

See Form

submit(name=None, index=None, extra_environ=None, timeout=None)[source]

Submits the form. If name is given, then also select that button (using index to disambiguate)``.

Returns a webtest.browser.TestResponse object.

Environment variables

Those value are used if found in environment:

  • SELENIUM_HOST: Default to

  • SELENIUM_PORT: Default to 4444

  • SELENIUM_BIND: IP used to bind extra servers (WSGI Server/File server). Default to

  • SELENIUM_DRIVER: The driver used to start the browser. Usualy something in *chrome, *firefox, *googlechrome. Default to *googlechrome. You can get the full list by running:

    $ java -jar selenium-server.jar -interactive
  • SELENIUM_KEEP_OPEN: If exist then browser session are not closed so you can introspect the problem on failure.

  • SELENIUM_JAR: If selenium is not running then this jar is used to run selenium.


Testing a wsgi application

class TestApp(unittest.TestCase):

    def setUp(self): = webtest.TestApp(application)

    def test_webtest(self):
        resp ='/', {'redirect': '/message.html?message=submited'})
        resp.mustcontain('It Works!')
        form = resp.forms['myform']

        self.assertEqual(form['mytext'].value, '')
        resp.mustcontain(no='Form submited')

        with webtest.selenium(resp) as sresp:
            if sresp:
                sform = sresp.forms['myform']
                sform['mytext'] = 'foo'
                sresp = sform.submit(name='go', timeout=0)
                sresp.mustcontain('Form submited')

        if resp.updated:
            resp.mustcontain('Form submited')
            form = resp.forms['myform']
            self.assertEqual(form['mytext'].value, 'foo')

        resp = form.submit(name='go')
        resp = resp.follow()

    def test_selenium(self):
        resp ='/', {'redirect': '/message.html?message=submited'})
        resp.mustcontain('It Works!')
        form = resp.forms['myform']

        form['mytext'] = 'foo'
        self.assertEqual(form['mytext'].value, 'foo')

        # file upload are only supported with *firefox *chrome drivers
        filename = os.path.join(files, 'html', 'index.html')
        file = form['myfile']
        file.value = (filename,)

        form['myradio'] = 'true'
        self.assertEqual(form['myradio'].value, 'true')
        check = form.get('mycheckbox', index=0)
        check.value = 'true'
        self.assertEqual(check.value, 'true')
        form['myselect'] = 'value2'
        form['myselect'] = 'value2'
        self.assertEqual(form['myselect'].value, 'value2')
        form['mymultiselect'] = ['value1', 'value3']
        self.assertEqual(form['mymultiselect'].value, ['value1', 'value3'])

        # there is an ajax hook on the page
        resp = form.submit(name='go', timeout=0)
        resp.mustcontain('Form submited')

        # but we can submit the form to get the non-javascript behavior
        resp = form.submit()
        resp = resp.follow()

Testing the jquery.ui website

class TestJQueryUI(unittest.TestCase):

    def setupClass(cls): = webtest.SeleniumApp(url='')

    def setUp(self):
        self.resp ='')

    def test_autocomplete(self):
        resp ='Autocomplete')
        field = resp.doc.xpath('//input[@id="tags"]')
        field.value = 'a'
        item = resp.doc.xpath('//ul[@role="listbox"]//a[.="AppleScript"]')
        field.value = resp.doc.css('#ui-active-menuitem').html()
        self.assertEqual(field.value, "AppleScript")

    def test_datepicker(self):
        resp ='Datepicker')
        field = resp.doc.datepicker
        self.assertIn('/16/', field.value)

    def test_dialog(self):
        resp ='Dialog')
        close = resp.doc.xpath('//div[@role="dialog"]//span[.="close"]')
        close.wait_and_click()'Modal form').click()
        resp.doc.button('Create new user').wait().click()
        form = resp.form
        form['name'].value = 'Gael'
        form['email'] = ''
        create = resp.doc.button('Create an account')
        pwd = form['password']
        pwd.value = 'pwd'
        resp.mustcontain('Length of password must be between 5 and 16.')
        pwd.value = 'passwd'

    def test_dropable(self):
        resp ='Droppable')
        draggable = resp.doc.draggable
        droppable = resp.doc.droppable
        self.assertTrue(droppable.hasClass('ui-state-highlight'))'Shopping Cart').click()
        cart = resp.doc.css('#cart ol.ui-droppable')
        item = resp.doc.xpath('//li[.="Lolcat Shirt"]')
        self.assertNotIn(item, cart)
        self.assertIn(item, cart)

    def teardownClass(cls):