Agile Zone is brought to you in partnership with:

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

Practical PHP Testing Patterns: Recorded Test

10.20.2010
| 9153 views |
  • submit to reddit

This is the first article of the new Practical PHP Testing Patterns series.

This series is the natural continuation of the Practical PHP Patterns series, which applies in the PHP world the patterns presented in the original Gang of Four book, and in Fowler's Pattern of Enterprise Application Architecture. We will continue this voyage by transporting to PHP code the xUnit Test Patterns, contained in Gerard Meszaros book.

We'll start with the test automation patterns, and we'll follow the order of the book throughout all the patterns emerging in our test suites.

Recorded Test

When applying the Recorded Test pattern, an automated test is prepared not by hand, but by executing it one time manually, and recording the interactions of the developer with the component. The test can then be played back by a tool capable of interpreting the gathered data.
Usually this kind of test involves the whole application and works at the acceptance level. The endpoint interested by the test is the user interface.

The most famous example of Recorded Test, at least in the web world, is probably Selenium IDE, a tool for generating tests for Selenium (which is a tool capable of running a real web browser with automated testing intents.) Selenium IDE works like this:

  • you open the browser to a certain URL, and start recording.
  • you click around, submit forms or follow links.
  • when you want, you can select text or part of the DOM to make an assertion.
  • you stop recording and cut the generated code.

You can choose different programming languages as the target of Selenium IDE generation process. I choose PHP usually, but also HTML if you want to interpret tests only in the browser. Selenium IDE will generate (not very clean) code for your automated tests that model the actions you had just performed.

Thanks to Recorded Test, acceptance tests can be quickly generated (or at least, their drafts can) by a developer with nearly no knowledge of Selenium, but only of how the application should be used.

Issues

A disadvantage of Recorded Test is that it is by definition only viable for regression testing: we cannot Test-Driven Develop an application with this pattern.

Moreover, the quality of the generated test code is not very high (read: it sucks), and if you plan to read it even one time, it really needs a revision by a human developer that adjusts the style and refactor the code before checking in the result in the test suite.

User interface test are also brittle, particularly in the case of generated ones: for example Selenium IDE generates selectors like #generatedIdOfDOMNode. You may want to change the selectors to something more appropriate to avoid a broken test the first time you change the order of JavaScript widgets.

A final note is that a Recorded Test does not take care about setting up a sandbox: for an in-memory component it would be simple, but mostly recorded tests are based on user interfaces; you'll have to setup by yourself, at each execution of the tests, a small sandbox with a fresh, ideal state like an empty database. Since we are talking about web applications, commonly the tool only records the actions taken in the browser and not you resetting your mysql database.

Variations

  • Refactored Recorded Test: a Recorded Test is used to generate some basic primitives, like 'fill and submit this form' and 'assert the table contains all these data'; generally they would be tedious and long to write. Then you can write other tests that use this building blocks.
  • External Test Recording: an external tool is responsible for generating the test, and exposes it as test code. This is sometimes takes for granted, but nothing keeps a recording tool from storing its internal representation of user actions, and repeat them when asked.
Selenium IDE can fit both these two variations.

Example

This is how a Recorded Test created by Selenium IDE looks like. No wonder the Refactored Recorded Test is by far preferred...
<?php

require_once 'PHPUnit/Extensions/SeleniumTestCase.php';

class Example extends PHPUnit_Extensions_SeleniumTestCase
{
  protected function setUp()
  {
    $this->setBrowser("*chrome");
    $this->setBrowserUrl("http://change-this-to-the-site-you-are-testing/");
  }

  public function testMyTestCase()
  {
    $this->open("/#sclient=psy&hl=it&q=test&aq=f&aqi=g5&aql=&oq=&gs_rfai=&pbx=1");
    try {
        $this->assertTrue($this->isTextPresent("Test-driven development"));
    } catch (PHPUnit_Framework_AssertionFailedError $e) {
        array_push($this->verificationErrors, $e->toString());
    }
  }
}
?>
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.)