Webdriver API

Starting with version 2, gocept.selenium also includes integration with Selenium’s webdriver backend, the plan being to keep our own API as backwards-compatible as possible during the 2.x release series and switching to a modernized API only with version 3.

This means that we’ve set out to implement the Selenese API on top of webdriver and while this has proven to be possible to a large extent, some details of the Selenese API don’t make any sense or are too different to be worth implementing in a webdriver environment.

Here’s how to set this up (see Integration for details):

import gocept.httpserverlayer.wsgi
import gocept.selenium
from mypackage import App

http_layer = gocept.httpserverlayer.wsgi.Layer(App())
webdriver_layer = gocept.selenium.WebdriverLayer(
    name='WSGILayer', bases=(http_layer,))
test_layer = gocept.selenium.WebdriverSeleneseLayer(
    name='WebdriverTestLayer', bases=(webdriver_layer))

class TestWSGITestCase(gocept.selenium.WebdriverSeleneseTestCase):

    layer = test_layer

    def test_something(self):
        self.selenium.open('http://%s/foo.html' % self.selenium.server)

Here’s a list of backwards-incompatibilities between using WebdriverSeleneseLayer and the (old) SeleniumRC-backed gocept.selenium.RCLayer:

  • getEval behaves differently.
    • getEval adds a return statement in front of the code, i.e. to run Javascript code which is not an expression, use runScript
    • getEval has access to different globals now: browserbot is no longer defined, while window and document refer directly to the window under test.
    • getEval returns the dictionary representation of objects instead of the rather uninformative [object Object].
  • The browser name syntax has changed: specify Firefox as “firefox”, not “firefox*” (concerns the environment variable for setting the browser, which used to be GOCEPT_SELENIUM_BROWSER and is GOCEPT_WEBDRIVER_BROWSER for webdriver). See the WebDriver wiki for possible browser names.
  • With Selenium Remote-Control one had to change the base Firefox profile to be used on the server side (by passing -firefoxProfileTemplate to selenium-server.jar). With WebDriver this has moved to the client side, so you can select a profile by setting the path to an existing Firefox profile as the environment variable GOCEPT_SELENIUM_FF_PROFILE.
  • Selenese methods that don’t work yet:
    • highlight
    • getSpeed
    • setSpeed
    • getAllWindowNames
    • getAllWindowTitles
    • selectPopUp
    • deselectPopUp
  • Selenese methods with changed behaviour:
    • open: dropped the ignoreResponseCode parameter
    • assertOrdered only works with relative xpath locators, not with any element locators anymore.
  • Selenese methods that have been removed and are not coming back:
    • addCustomRequestHeader
    • addLocationStrategy
    • addScript
    • allowNativeXpath
    • answerOnNextPrompt
    • assignId
    • captureNetworkTraffic
    • chooseCancelOnNextConfirmation
    • chooseOkOnNextConfirmation
    • fireEvent
    • focus
    • getMouseSpeed
    • getTable
    • ignoreAttributesWithoutValue
    • removeScript
    • retrieveLastRemoteControlLogs
    • setBrowserLogLevel
    • setContext
    • setCursorPosition
    • setMouseSpeed
    • useXpathLibrary
    • waitForFrameToLoad
  • Locator patterns that can no longer be used:
    • option: id
    • frame: relative, dom

On the other hand, here are some new features that only WebdriverSeleneseLayer offers:

  • Locator js (or dom or anything that starts with document): Find an element by evaluating a javascript expression. Example: getText('js=document.getElementsByClassName("foo")')
  • Convenience locator jquery (when your site already loads jQuery). Example: getText('jquery=.foo') (this is the equivalent of getText('js=window.jQuery(".foo")[0]'))