PHPUnit-Selenium2 Cheat Sheet

My PHPUnit-Selenium2 Cheat Sheet

Here are a few snippets of how I’ve achieved various tasks, some tricks and patterns in phpunit/phpunit-selenium v2.0 – targeting Selenium2. I’ll try to keep this updated with more techniques over time.


I wrote this small hook to make screenshots automatic, like they used to be. Of course you may want to put a timestamp in the file, but I usually only want the last problem.

 * PhpUnitSelenium v1 used to have automatic screenshot as a feature, in v2 you have to do it "manually".
public function onNotSuccessfulTest(Exception $e){
 file_put_contents(__DIR__.'/../../out/screenshots/screenshot1.png', $this->currentScreenshot());


Waiting for stuff

An eternal issue in automated testing is latency and timeouts. Particularly problematic in anything other than a standard onclick-pageload cycle, such as pop-up calendars or a JS app. Again I felt the move from Selenium1 to 2 made this much more clumsy, so I wrote this simple wrapper for the common wait pattern boilerplate.

 * Utility method to wait for an element to appear.
 * @param string $selector
 * @param int    $timeout milliseconds wait cap, after which you'll get an error
protected function waitFor($selector, $timeout=self::WAIT_TIMEOUT_MS){
 $this->waitUntil(function(PHPUnit_Extensions_Selenium2TestCase $testCase) use($selector){
  try {
  } catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {
   return null;
  return true;
 }, $timeout);

Checking for the right page, reliably.

If something goes wrong in a complex test with lots of interactions, it’s important to fail fast  – for example if the wrong page loads, nothing else will work very well. So I always check the page being tested is the right page. To do this reliably, not using content or design-specific elements, I add a <body> tag “id” attribute to every page (you could use body class if you’re already using that styling technique but I tend to separate my QA tagging from CSS dependencies). Then I added this assertion to my base test case.

 * We use <body id="XXX"> to identify pages reliably.
 * @param $id
protected function assertBodyIDEquals($id){
 $this->assertEquals($id, $this->byCssSelector('body')->attribute('id'));

Getting Value

The ->value() method was removed in Selenium v2.42.0. The replacement method is to use $element->attribute(‘value’) [source]

// old way
//$sCurrentStimulus = $this->byName('word_index')->value();
// new way
$sCurrentStimulus = $this->byName('word_index')->attribute('value');
// I actually use this now:
$sCurrentStimulus = $this->byCssSelector('input[name=word_index]')->attribute('value');

However ->value() was also a mutator (setter), which ->attribute() is not. So if you want to update a value, people say you have to resort to injecting JavaScript into the page, which I found somewhat distasteful. However luckily this is not the case for the “value” attribute specifically, according to the source code, it’s only the GET which was removed from ->value().

JSON Wire Protocol only supports POST to /value now. To get the value of an element GET /attribute/:naem should be used

So I can carry on doing this, presumably until the next update breaks everything.


General Page Tests

I have one test suite that just whips through a list of all known pages on a site and scans them for errors, a visual regression smoke test for really stupid errors. It’s also easy to drop a call to this method in at the beginning of any test. When I spot other visual errors occurring, I can add them to the list.

 * Looks for in-page errors.
protected function checkErrors() {
 $txt = $this->byTag('body')->text();
 $src = $this->source();

 // Removed: This false-positives on the news page.
 //$this->assertNotContains('error', $this->byTag('body')->text());

 // Standard CI errors
 $this->assertNotContains('A Database Error Occurred', $txt);
 $this->assertNotContains('404 Page Not Found', $txt);
 $this->assertNotContains('An Error Was Encountered', $txt);
 // PHP errors
 $this->assertNotContains('Fatal error: :', $txt);
 $this->assertNotContains('Parse error:', $txt);

 // the source might have hidden errors, but then it also might contain the word error? false positive?
 // This false positives in the user form (must have validation error text!
 //$this->assertNotContains('error', $this->source());
 $this->assertNotContains('xdebug-error', $src); // XDebug wrapper class



This entry was posted in articles and tagged , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *