Using Selenium with PHPUnit

Testing is a really wide subject, whether it be unit testing, functional testing, acceptance testing, etc. In this article, we’re going to see how you can do acceptance testing using Selenium. I will use a practical example to illustrate a real use case. I will assume that you already know how to do unit testing using PHPUnit, or that you at least have a grasp of what it’s all about. Let’s get started.

What Is Acceptance Testing?

Acceptance testing is the process of telling user stories through tests, and I love this quote to describe it:

A formal test conducted to determine whether or not a system satisfies its acceptance criteria and to enable the customer to determine whether or not to accept the system.

What Is Selenium?

Selenium is a tool to automate user interface testing. It helps with testing your application against the browser. The process could be described like so:

Go to the page http://myapp.dev/videos.

Assert the page contains a list of 20 videos.

Click number two on the pagination.

Assert the page contains a list of 20 videos.

Quit the browser.

You may be wondering: “How does it manipulate the web page using the described tests?”

The answer is “it depends”. If you’re using Selenium RC (previously named Selenium 1), it will inject auto generated JavaScript code to the page to perform the desired actions. Selenium RC is deprecated and is only supported in maintenance mode; you should be using Selenium WebDriver.

When using Selenium WebDriver (Selenium 2), the tests are translated into commands and passed to the Selenium server (more about that in a moment), then passed to the browser using the web browser native API.

Application Setup

Because we don’t actually have an application to test, I’m going to use a user registration page. The user will enter his personal information and some billing info. If everything is good, the page should output Everything is Good!. Otherwise, the page will show the subscription form with a list of validation error messages.

We will start testing our application using PHPUnit with the Selenium extension. Be sure to install them using Composer before starting.

We said before that commands are passed to a Selenium server, which then forwards them to the browser. We need to download the Selenium server, which is just a JAVA archive executable. The server can be run using java -jar selenium-server-standalone-<version>.jar. Since we will be using it frequently, it’s a good idea to move it to a bin directory and make an alias for that inside our .bashrc or .zshrc.

PHPUnit and Selenium

PHPUnit supports both Selenium RC and WebDriver, and it provides two classes for that purpose. The PHPUnit_Extensions_SeleniumTestCase is used for the RC version, and the PHPUnit_Extensions_Selenium2TestCase is used for the WebDriver version. So, your test must extend one of them to get started. Please remember that the RC version is being deprecated, so we’ll use the WebDriver one in our example below.

The setUp method is used for preparing the test environment. In this case, we use it to tell PHPUnit where our Selenium server is running, what browser we’ll be using and the URL of our application. The setHost method defaults to localhost and the setPort method defaults to 4444, so they can be omitted here. However, this can be used if your testing server is inside a Windows machine that supports Internet Explorer while you run your tests from another different machine, etc.

The tearDown method is called when the tests are done, and it’s used to clear the stage. We use it to close the browser and terminate the current session.

public function tearDown()
{
$this->stop();
}

Data Providers

PHPUnit data providers allow us to feed our tests with specific data without having to iterate over it. You can read more in the documentation.

The invalidInputsProvider returns a list of valid inputs except for one field, and we pass along the expected error message after the validation fails.

Working With DOM Elements

One common task when working with web pages is element selection. PHPunit’s Selenium extension provides a really nice API for that. You can select elements by class name, tag, name, ID, CSS selector, XPath, etc. The method will return a PHPUnit_Extensions_Selenium2TestCase_Element instance which you can use to select other child elements, attributes, etc. You can also set or get the element value, update element CSS and a bunch of other common tasks. For our page we may do something like the following.

This test will select the username input and set a value, then submit the subscription form. We can add an assertion after that to see if the response is as expected. The page body will contain Everything is Good! if the validation passed.

Valid Form Submission

To point the browser to a specific page we use the url method from the PHPUnit_Extensions_Selenium2TestCase class. The URL is relative to the one provided to the setBrowserUrl method. So, after pointing the browser to the index page we fill and submit the form, then test the expected success message.

Assuming your Selenium server is up and running, go ahead and run your tests with phpunit tests/acceptance/UserSubscriptionTest.php. This will create a new browser session and start filling the form. We are expecting everything to pass with one successful assertion.

Some of the tests fail, and the testing duration is too short for us to observe what went wrong. PHPUnit has the ability to capture screenshots of failing tests using the currentScreenshot method which returns a BLOB image that we can save.

Invalid Form Submission

The invalid form submission is almost identical to the previous method. We fill in the form inputs and submit. Then, we verify that the validation error message is as expected. We will be using the invalidInputsProvider I mentioned earlier.

The byCssSelector method allows us to retrieve an element from the page using CSS selectors, in this case the error paragraph. We assert if the error message is as expected using the error message field from the data provider method.

Our form contains only basic interactions like selecting elements, setting values, submitting the form, etc. However, we can also use the click method on a button or link element to verify that the target page is working as expected.

Using Another Browser

We used the Firefox browser for our tests. However, we have the ability to use any other browser as well. Selenium uses the driver approach, where every browser vendor works on providing its own driver. You can check the list of supported drivers in the documentation.

To enable the Chrome browser, you need to download the chromeDriver and specify the path as an option when launching the Selenium server.

The callback function will wait until we return a non null value, and will timeout after two seconds with an error message. The lookup method will keep looking for the element, but if you want to specify a searching interval you can use the implicitWait method.

$this->timeouts()->implicitWait(300); //milliseconds

Conclusion

This article was a brief introduction to using Selenium with PHPUnit for acceptance testing. In general, you can use Selenium for anything that requires browser automation. If you have any comments or questions, be sure to post them below and I will do my best to answer them.

Younes is a freelance web developer, technical writer and a blogger from Morocco. He's worked with JAVA, J2EE, JavaScript, etc., but his language of choice is PHP. You can learn more about him on his website.