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

browser[source]

The current Selenium

close()[source]

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')
webtest.sel.selenium(obj)[source]

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]
doc[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

css(selector)[source]

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

xpath(path)[source]

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:

element.fireEvent('focus')

Or a more pythonic name:

element.fire_event('focus')

Both are equal to:

browser.execute('fireEvent', element.locator, 'focus')
attr(attr)[source]

Return the attribute value of the element

drag_and_drop(element)[source]

Drag and drop to element

eval(*expr)[source]

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
exist()[source]

return true is the element is present

hasClass(name)[source]

True iif the class is present

html()[source]

Return the innerHTML of the element

text()[source]

Return the text of the element

wait(timeout=3000)[source]

Wait for an element and return this element

wait_and_click(timeout=3000)[source]

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 127.0.0.1

  • SELENIUM_PORT: Default to 4444

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

  • 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
    cmd=getNewBrowserSession
  • 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.

Examples

Testing a wsgi application

class TestApp(unittest.TestCase):

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

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

        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()
        resp.mustcontain('<pre>submited</pre>')

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

        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()
        resp.mustcontain('<pre>submited</pre>')

Testing the jquery.ui website

class TestJQueryUI(unittest.TestCase):

    @classmethod
    def setupClass(cls):
        cls.app = webtest.SeleniumApp(url='http://jqueryui.com/')

    def setUp(self):
        self.resp = self.app.get('http://jqueryui.com/demos/')

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

    def test_datepicker(self):
        resp = self.resp.click('Datepicker')
        field = resp.doc.datepicker
        field.fireEvent('focus')
        resp.doc.link('16').wait_and_click()
        self.assertIn('/16/', field.value)

    def test_dialog(self):
        resp = self.resp.click('Dialog')
        close = resp.doc.xpath('//div[@role="dialog"]//span[.="close"]')
        close.wait_and_click()
        resp.doc.link('Modal form').click()
        resp.doc.button('Create new user').wait().click()
        form = resp.form
        form['name'].value = 'Gael'
        form['email'] = 'gael@gawel.org'
        create = resp.doc.button('Create an account')
        create.click()
        pwd = form['password']
        self.assertTrue(pwd.hasClass('ui-state-error'))
        pwd.value = 'pwd'
        create.click()
        resp.mustcontain('Length of password must be between 5 and 16.')
        pwd.value = 'passwd'
        create.click()
        resp.mustcontain('<td>Gael</td>')

    def test_dropable(self):
        resp = self.resp.click('Droppable')
        draggable = resp.doc.draggable
        droppable = resp.doc.droppable
        self.assertFalse(droppable.hasClass('ui-state-highlight'))
        draggable.drag_and_drop(droppable)
        self.assertTrue(droppable.hasClass('ui-state-highlight'))

        resp.doc.link('Shopping Cart').click()
        cart = resp.doc.css('#cart ol.ui-droppable')
        cart.wait()
        item = resp.doc.xpath('//li[.="Lolcat Shirt"]')
        self.assertNotIn(item, cart)
        item.drag_and_drop(cart)
        self.assertIn(item, cart)

    @classmethod
    def teardownClass(cls):
        cls.app.close()