Приглашаем посетить
Спорт (www.sport-data.ru)

Unit Testing in a Web Environment

Previous
Table of Contents
Next

Unit Testing in a Web Environment

When I speak with developers about unit testing in PHP in the past, they often said "PHP is a Web-centric language, and it's really hard to unit test Web pages." This is not really true, however.

With just a reasonable separation of presentation logic from business logic, the vast majority of application code can be unit tested and certified completely independently of the Web. The small portion of code that cannot be tested independently of the Web can be validated through the curl extension.

About curl

curl is a client library that supports file transfer over an incredibly wide variety of Internet protocols (for example, FTP, HTTP, HTTPS, LDAP). The best part about curl is that it provides highly granular access to the requests and responses, making it easy to emulate a client browser. To enable curl, you must either configure PHP by using --with-curl if you are building it from source code, or you must ensure that your binary build has curl enabled.


We will talk about user authentication in much greater depth in Chapter 13, "User Authentication and Session Security" but for now let's evaluate a simple example. You can write a simple inline authentication system that attempts to validate a user based on his or her user cookie. If the cookie is found, this HTML comment is added to the page:

<!-- crafted for NAME !>

First, you need to create a unit test. You can use curl to send a user=george cookie to the authentication page and then try to match the comment that should be set for that user. For completeness, you can also test to make sure that if you do not pass a cookie, you do not get authenticated. Here's how you do all this:

<?php
require_once "PHPUnit/Framework/TestCase.php";

// WebAuthCase is an abstract class which just sets up the
// url for testing but runs no actual tests.
class WebAuthTestCase extends PHPUnit_Framework_TestCase{
  public $curl_handle;
  public $url;
  function _ _construct($name) {
    parent::_ _construct($name);
  }
  function setUp() {
    // initialize curl
    $this->curl_handle = curl_init();
    // set curl to return the response back to us after curl_exec
    curl_setopt($this->curl_handle, CURLOPT_RETURNTRANSFER, 1);
    // set the url
    $this->url = "http://devel.omniti.com/auth.php";
    curl_setopt($this->curl_handle, CURLOPT_URL, $this->url);
  }
  function tearDown() {
    // close our curl session when we're finished
    curl_close($this->curl_handle);
  }
}

// WebGoodAuthTestCase implements a test of successful authentication
class WebGoodAuthTestCase extends WebAuthTestCase {
  function _ _construct($name) {
    parent::_ _construct($name) ;
  }
  function testGoodAuth() {
    $user = 'george';
    // Consturct a user=NAME cookie
    $cookie = "user=$user;";
    // Set the cookie to be sent
    curl_setopt($this->curl_handle, CURLOPT_COOKIE, $cookie);
    // execute our query
    $ret = curl_exec($this->curl_handle);
    $this->assertRegExp("/<!-- crafted for $user -->/", $ret);
  }
}

// WebBadAuthTestCase implements a test of unsuccessful authentication
class WebBadAuthTestCase extends WebAuthTestCase {
  function _ _construct($name) {
    parent::_ _construct($name);
  }
  function testBadAuth() {
    // Don't pass a cookie
    curl_setopt($this->curl_handle, CURLOPT_COOKIE, $cookie);
// execute our query
    $ret = curl_exec($this->curl_handle);
    if(preg_match("/<!-- crafted for /", $ret)) {
      $this->fail();
    }
    else {
     $this->pass();
    }
  }
}
if(realpath($_SERVER['PHP_SELF']) == _ _FILE_ _) {
  require_once "PHPUnit/Framework/TestSuite.php";
  require_once "PHPUnit/TextUI/TestRunner.php";

  $suite = new PHPUnit_Framework_TestSuite('WebGoodAuthTestCase');
  $suite->addTestSuite("WebBadAuthTestCase");
  PHPUnit_TextUI_TestRunner::run($suite);
}
?>

In contrast with the unit test, the test page is very simplejust a simple block that adds a header when a successful cookie is matched:

<HTML>
<BODY>
<?php
  if($_COOKIE[user]) {
    echo "<!-- crafted for $_COOKIE[user] -->";
  }
?>
<?php print_r($_COOKIE) ?>
Hello World.
</BODY>
</HTML>

This test is extremely rudimentary, but it illustrates how you can use curl and simple pattern matching to easily simulate Web traffic. In Chapter 13, "User Authentication and Session Security," which discusses session management and authentication in greater detail, you use this WebAuthTestCase infrastructure to test some real authentication libraries.


Previous
Table of Contents
Next