PHP
  Home arrow PHP arrow Unit Testing in Detail
Dev Shed Forums  
Administration  
AJAX  
Apache  
BrainDump  
DHTML  
Flash  
Java  
JavaScript  
Multimedia  
MySQL  
Oracle  
Perl  
PHP  
Practices  
Python  
Reviews  
Security  
Smartphone Development  
Style-Sheets  
Web Services  
XML  
Zend  
Zope  
Mobile Linux  
App Generation ROI  
IBM® developerWorks  
Forums Sitemap  
E-Commerce Hosting  
Linux Web Hosting  
Managed Hosting  
Small Business Hosting  
VPS Hosting  
Weekly Newsletter

 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid  
Request Media Kit
Contact Us  
Site Map  
Privacy Policy  
Support  
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
Google.com  
PHP

Unit Testing in Detail
By: Sams Publishing
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: starstarstarstarstar / 2
    2006-10-26


    Table of Contents:
  • Unit Testing in Detail
  • Additional Features in PHPUnit
  • Adding More Test Conditions
  • Adding Listeners

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      error-file:tidyout.log Del.ici.ous error-file:tidyout.log Digg
      error-file:tidyout.log Blink error-file:tidyout.log Simpy
      error-file:tidyout.log Google error-file:tidyout.log Spurl
      error-file:tidyout.log Y! MyWeb error-file:tidyout.log Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article

     
     
    ADVERTISEMENT


    Unit Testing in Detail
    ( Page 1 of 4 )

    Last week, we introduced you to setting up a unit testing framework. This week, you will learn about running multiple tests simultaneously, creating more informative error messages, and more. This article, the second of three parts, is excerpted from chapter 6 of the book Advanced PHP Programming, written by George Schlossnagle (Sams; ISBN: 0672325616).

    Separate Test Packaging

    Given the drawbacks to inlining tests, I choose to avoid that strategy and write my tests in their own files. For exterior tests, there are a number of different philosophies. Some people prefer to go the route of creating a t or tests subdirectory in each library directory for depositing test code. (This method has been the standard method for regression testing in Perl and was recently adopted for testing the PHP source build tree.) Others opt to place tests directly alongside their source files. There are organizational benefits to both of these methods, so it is largely a personal choice. To keep our examples clean here, I use the latter approach. For every library.inc file, you need to create a library.phpt file that contains all the PHPUnit_Framework_TestCase objects you define for it.

    In your test script you can use a trick similar to one that you used earlier in this chapter: You can wrap a PHPUnit_Framework_TestSuite creation and run a check to see whether the test code is being executed directly. That way, you can easily run the particular tests in that file (by executing directly) or include them in a larger testing harness.

    EmailAddress.phpt looks like this:

    <?php
    require_once "EmailAddress.inc";
    require_once 'PHPUnit/Framework/TestSuite.php';
    require_once 'PHPUnit/TextUI/TestRunner.php';
    
    class EmailAddressTestCase extends
    PHPUnit_Framework_TestCase { public function _ _construct($name) { parent::_ _construct($name); } public function testLocalPart() { $email = new EmailAddress("george@omniti.com"); // check that the local part of the address is
    equal to 'george' $this->assertTrue($email->localPart == 'george') ; } public function testDomain() { $email = new EmailAddress("george@omniti.com"); $this->assertTrue($email->domain == 'omniti.com'); } } if(realpath($_SERVER[PHP_SELF]) == _ _FILE_ _) { $suite = new
    PHPUnit_Framework_TestSuite('EmailAddressTestCase'); PHPUnit_TextUI_TestRunner::run($suite); } ?>

    In addition to being able to include tests as part of a larger harness, you can execute EmailAddress.phpt directly, to run just its own tests:

    PHPUnit 1.0.0-dev by Sebastian Bergmann.
    
    ..
    
    Time: 0.0028760433197
    
    OK (2 tests)

    Running Multiple Tests Simultaneously

    As the size of an application grows, refactoring can easily become a nightmare. I have seen million-line code bases where bugs went unaddressed simply because the code was tied to too many critical components to risk breaking. The real problem was not that the code was too pervasively used; rather, it was that there was no reliable way to test the components of the application to determine the impact of any refactoring.

    I'm a lazy guy. I think most developers are also lazy, and this is not necessarily a vice. As easy as it is to write a single regression test, if there is no easy way to test my entire application, I test only the part that is easy. Fortunately, it's easy to bundle a number of distinct TestCase objects into a larger regression test. To run multiple TestCase objects in a single suite, you simply use the addTestSuite() method to add the class to the suite. Here's how you do it:

    <?php
    require_once "EmailAddress.phpt";
    require_once "Text/Word.phpt";
    require_once "PHPUnit/Framework/TestSuite.php";
    require_once "PHPUnit/TextUI/TestRunner.php";
    
    $suite = new PHPUnit_Framework_TestSuite();
    $suite->addTestSuite('EmailAddressTestCase');
    $suite->addTestSuite('Text/WordTestCase');
    
    PHPUnit_TextUI_TestRunner::run($suite);
    ?>

    Alternatively, you can take a cue from the autoregistration ability of PHPUnit_Framework_TestSuite to make a fully autoregistering testing harness. Similarly to the naming convention for test methods to be autoloaded, you can require that all autoloadable PHPUnit_Framework_TestCase subclasses have names that end in TestCase. You can then look through the list of declared classes and add all matching classes to the master suite. Here's how this works:

    <?php
    require_once "PHPUnit/FrameWork/TestSuite.php";
    
    class TestHarness extends
    PHPUnit_Framework_TestSuite { private $seen = array(); public function _ _construct() { $this = parent::_ _construct(); foreach( get_declared_classes() as $class) { $this->seen[$class] = 1; } } public function register($file) { require_once($file); foreach( get_declared_classes() as $class) { if(array_key_exists($class, $this->seen)) { continue; } $this->seen[$class] = 1; // ZE lower-cases class names, so we look for
    "testcase" if(substr($class, -8, 8) == 'testcase') { print "adding $class\n"; $this->addTestSuite($class); } } } } ?>

    To use the TestHarness class, you simply need to register the files that contain the test classes, and if their names end in TestCase, they will be registered and run. In the following example, you write a wrapper that uses TestHarness to autoload all the test cases in EmailAddress.phpt and Text/Word.phpt:

    <?php
    require_once "TestHarness.php";
    require_once "PHPUnit/TextUI/TestRunner.php";
    
    $suite = new TestHarness();
    $suite->register("EmailAddress.phpt");
    $suite->register("Text/Word.phpt");
    PHPUnit_TextUI_TestRunner::run($suite);
    ?>

    This makes it easy to automatically run all the PHPUnit_Framework_TestCase objects for a project from one central location. This is a blessing when you're refactoring central libraries in an API that could affect a number of disparate parts of the application.



     
     
    >>> More PHP Articles          >>> More By Sams Publishing
     

       

    PHP ARTICLES

    - Getting Data from Yahoo Site Explorer Inboun...
    - Method Chaining: Adding More Selecting Metho...
    - How to Split a File During an FTP Upload Usi...
    - Expanding a Custom CodeIgniter Library with ...
    - Using the Yahoo Site Explorer Inbound Links ...
    - Building a CodeIgniter Custom Library with M...
    - Building an E-mini Trading System Using PHP ...
    - Completing the MySQL Class with Method Chain...
    - Building Dynamic Queries with Chainable Meth...
    - PHP Encryption and Decryption Methods
    - Building a MySQL Abstraction Class with Meth...
    - Completing a Sample String Processor with Me...
    - Mastering WHILE Loops for PHP and MySQL
    - Method Chaining: Adding More Methods to the ...
    - Method Chaining in PHP 5





    © 2003-2009 by Developer Shed. All rights reserved. DS Cluster 2 Hosted by Hostway
    For more Enterprise Application Development news, visit eWeek