I am a programmer and architect (the kind that writes code) with a focus on testing and open source; I maintain the PHPUnit_Selenium project. I believe programming is one of the hardest and most beautiful jobs in the world. Giorgio is a DZone MVB and is not an employee of DZone and has posted 638 posts at DZone. You can read more from them at their website. View Full User Profile

PHPUnit_Selenium

01.19.2012
| 11828 views |
  • submit to reddit
With the 1.2 release, PHPUnit_Selenium supports (basically) for the first time the Selenium 2 WebDriver API. While PHPUnit_Selenium already worked with Selenium 2, it did so only by using the Selenium 1 emulation included in the jar; now it provides an object-oriented API right natively supported in a base PHPUnit test case, shipped in PHPUnit's PEAR channel.

Installation

Installation is usually easier via PEAR, which will install the library for all the users of the machine:
sudo pear channel-discover pear.phpunit.de      # not necessary if you already have PHPUnit
sudo pear install phpunit/PHPUnit_Selenium
To upgrade the library instead, execute:
sudo pear upgrade phpunit/PHPUnit_Selenium
You may have to upgrade pear itself prior to the installation:
sudo pear upgrade pear

if your distribution/OS X does not ship a version of PEAR newer enough to satisfy PHPUnit dependencies.

Setup

The old API is still supported and will be for the foreseeable future, as long as Selenium 2 continues to emulate it; it is available by subclassing the PHPUnit_Extensions_SeleniumTestCase class and the usage is extensively described in the manual.

The WebDriver API is instead provided by PHPUnit_Extensions_Selenium2TestCase:

class Extensions_Selenium2TestCaseTest extends PHPUnit_Extensions_Selenium2TestCase
{
    public function setUp()
    {
        $this->setHost('localhost');
        $this->setPort(4444);           // standard values if you're using a JAR locally
        $this->setBrowser('firefox');   // no * prefixes
        $this->setBrowserUrl('http://google.com');     // the URL where to start
    }
}

The setters API is identical to the old one, apart from the browser name not needing a '*' prefix like in '*chrome'.

Moving around

There are two basic concepts in the API, Session and Element objects. All methods called on the test case object are automatically delegated to the current Session (an instance of PHPUnit_Extensions_Selenium2TestCase_Session); you can obtain Elements by selecting them in the current page via the Session.

$this->url('folder/index.php') and $this->url() specify a new location for the browser and retrieve the current one, respectively. $this->title() shows you the <title> of the current page.

Element selection

You can select elements in any imaginable way, from class names to css selectors to attributes like id and name, or even XPath queries. All these methods return a PHPUnit_Extensions_Selenium2TestCase_Element object.

   public function testShortenedApiForSelectionOfElement()
    {
        $this->url('html/test_element_selection.html');

        $element = $this->byClassName('theDivClass');
        $this->assertEquals('The right div', $element->text());

        $element = $this->byCssSelector('div.theDivClass');
        $this->assertEquals('The right div', $element->text());

        $element = $this->byId('theDivId');
        $this->assertEquals('The right div', $element->text());

        $element = $this->byName('theDivName');
        $this->assertEquals('The right div', $element->text());

        $element = $this->byXPath('//div[@id]');
        $this->assertEquals('The right div', $element->text());
    }

Interacting

You can call click() on Element objects; a shorthand for this operation is $this->clickOnElement($id).

Elements also support text() to see the content of ordinary elements, and value() to set or get the value of form elements.

    public function testTypingViaTheKeyboard()
    {
        $this->url('html/test_type_page1.html');
        $usernameInput = $this->byName('username');
        $usernameInput->value('TestUser');
        $this->assertEquals('TestUser', $usernameInput->value());

        $passwordInput = $this->byName('password');
        $passwordInput->value('testUserPassword');
        $this->assertEquals('testUserPassword', $passwordInput->value());

        $this->clickOnElement('submitButton');
        $h2 = $this->byCssSelector('h2');
        $this->assertRegExp('/Welcome, TestUser!/', $h2->text());
    }

Conclusions

The best API documentation is made of code samples, and since they are part of CI and you are sure that they will always be up to date.

PHPUnit_Selenium means running a browser right inside your PHPUnit test suite, and Selenium supports both local instances and running in the cloud. End to end tests written with this tool can execute JavaScript inside pages and simulate the real user experience, catching regressions due to the lack of integration between the client and server sides. Since it's all PHP code, you can run verifications via a backdoor (like accessing the database directly) or reuse your test code for loading fixtures.

The support inside PHPUnit_Selenium is not complete yet, but I'm getting some feedback from users before completing it. I assure you that many basic cases are covered by the commands shown earlier, and that supporting new ones is a matter of adding a class a dozen of lines of code long.

Published at DZone with permission of Giorgio Sironi, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Fred Jiles replied on Fri, 2012/01/20 - 1:14pm

On ubuntu 11.10 when I do an install using pear install phpunit/PHPUnit_Selenium it appears to install. Even when I run pear info phpunit/PHPUnit_Selenium it shows 1.2.0 as the version. However there is no Selenium2TestCase.php file or folder in /usr/share/php/PHPUnit/Extensions and I get an error when using \PHPUnit_Extensions_Selenium2TestCase I have tried uninstall and installing again same thing. Any advice or anything I might be missing? version of PHPUnit is 3.6.7

Giorgio Sironi replied on Sat, 2012/01/21 - 7:58am in response to: Fred Jiles

We are in the process of releasing 1.2.1 due to an error in the package definition file, while the code works when checked out from Github. Thanks for your feedback.

Roberto Braga replied on Thu, 2012/01/26 - 5:30am

I tried to use it a bit but seem to lack of some functionalities, like window and frame selector. Is the selenium2 protocol fully supported and I didn't guess how to do or is still partial?

Giorgio Sironi replied on Sun, 2012/01/29 - 8:24am in response to: Roberto Braga

As noted in the conclusions, the support is partial; completing it is a matter of implementing new SessionCommand and ElementCommand object (usually 10-line classes).

Hannu Korhonen replied on Thu, 2012/05/24 - 5:28am

Thanks for the great work for PHPUnit_Selenium! I've been happily using PHPUnit_Extensions_Selenium2TestCase class. In my tests, I would need to emulate Shift-key press. How do you do this with this API? Is it supported?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.