This article is followup of the previous two Selenium testing in Drupal and Run Selenium tests in Drupal on Debian headless. I strongly recommend to read these two articles (at least watch demo videos) before reading more technical explanation below.
Now is the time to explain how to write tests using Selenium in simpletest.
In order to write selenium test we need to extend DrupalSeleniumWebTestCase class. This class on setUp starts new Firefox session. We can manipulate to connection with Firefox using driver property of the class.
So after we have established connection to Firefox we can do all our magic.
Some of methods of DrupalSeleniumWebTestCase
drupalGet -- open specified url in browser.
drupalPost -- submits the form on specified page (analog of DrupalWebTestCase drupalPost)
verboseScreenshot -- take a screenshot of whole page
drupalLogin -- log in user. Browser will go to /user page and submit all username and password specified in $user object. Works similar way to DrupalWebTestCase implementation.
drupalLogout -- log out current user
assertTitle -- assert titles of the page
assertLink -- assert existance of the link by its label
assertTextHelper -- helper for assertText and assertNoText so you can use these two asserts
Other methods are accessible via methods of SeleniumWebdriver (instance of this class is in $this->driver property).
I think most important methods for us are:
getElement($locator) -- find element on the page and return object of SeleniumWebElement class that represents this element. Afterwards we can do actions on this element. More details below.
getAllElements($locator) -- find all elements on the page that can be found with specified locator
These are strings that can be used to find elements on the page. Selenium has following types of locators:
css -- find element by its CSS selector
id -- find element by its identifier. Example $this->getElement('id=edit-submit')
name -- find form element by its name attribute. Example $this->getElement('name=pass')
class -- find element by its class. Example $this->getElement('class=form-item')
link -- find link by its label. Example $this->getElement('link=Log out')
partial link text -- find link by its partial label. Example $this->getElement('partial link text=out')
xpath -- find element by its xpath. Example $this->getElement('xpath=//*[@id="header"]')
tag name -- find element by its tag name. Example $this->getElement('tag name=input')
Most interesting for us of course is css selector. It allows us to use selectors that we use in jquery. Selenium uses sizzle library for that. So we can use expressions like:
css=div.region-header div.social-links a
This is really great feature. Selenium announced that we can use full CSS 3 selectors but I haven't managed to use selectors with values like:
Well, maybe I am missing something or maybe current Selenium only implements CSS 2 selectors. More information about selectors http://saucelabs.com/blog/index.php/2011/01/why-jquery-in-selenium-css-l...
Coming back to SeleniumWebElement class object that we get after call $this->getElement. We can do tons with it. Like:
click -- click on element
clear -- clear the value (workable example textfield in the form)
getAttributeValue -- get the value of the specified attribute
getText -- get text of the element (for example lable of the link)
getValue -- get value of the element
sendKeys -- send keys to element (like fill textfield)
dragAndDrop -- drag and drop element
Example of the code:
$this->driver->getElement('css=#edit-name')->sendKeys($user->name); $this->driver->getElement('css=#edit-pass')->sendKeys($user->pass_raw); $this->driver->getElement('css=#edit-submit')->submit();
Of course more methods and how they work you can look in the code.
I hope you have enjoyed possibilities of Selenium framework and find writing tests quite simple. I think we will need to implement more methods "like" in DrupalWebTestCase to DrupalSeleniumWebTestCase in order to make developers already familiar with methods names.
I am sure names of the methods and code will change after more people review. I will try to keep this document updated on changes.