Running PHPUnit
PHPUnit is run using the 'zero php' command line.
- zero create /my/workspace/phpunit
- Add this line (or similar) to ivy.xml
<dependency name="zero.php" org="zero" rev="[1.1.1.1, 2.0.0.0["/>
Note that it is important that the minimum revision of zero.core and zero.php that can be used with PHPUnit is 1.1.1.1. (also known as 'monza'). Prior to Monza sMash did not have a PHP commandline implementation.
Obtain a tarball of version 3.3.10 of the PHPUnit code from the link in point (1) of the manual installation instructions for PHPUnit
here and extract it into a temporary directory. The file will extract into PHPUnit-3.3.10/PHPUnit. Change directory to PHPUnit-3.3.10/PHPUnit and make a second tarfile from the contents, copy this tar file to the app/scripts/PHPUnit/ directory of the zero PHPUnit application and extract it. Finally create a file called phpunit.php in the app/scripts directory, the contents of the file are:
<?php
/* PHPUnit
*
* Copyright (c) 2002-2008, Sebastian Bergmann .
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $Id: PhpPHPUnit.txt,v 1.18 2009/07/31 22:59:55 nicholsr Exp $
*/
include ('../scripts/outeriterator.inc');
include('../scripts/filteriterator.inc');
include('../scripts/recursiveiterator.inc');
include('../scripts/appenditerator.inc');
include('../scripts/recursiveiteratoriterator.inc');
require_once 'PHPUnit/Util/Filter.php';
PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
require 'PHPUnit/TextUI/Command.php';
This is exactly the script that PHPUnit is started with but some SPL classes are not yet implemented in ProjectZero so the PHP implementations of those classes have been used instead. These are available from a standard PHP build and can be found under ext/spl/examples and also need to be copied into the project's app/scripts directory.
At this stage you should be able to run PHPUnit from the command line. To check that try using:
/my/zero/installation/zero php phpunit --h
This should produce the help text from PHPUnit.
The next step is to try running a PHPUnit test. Here is the test:
<?php
require_once 'PHPUnit/Framework.php';
include 'HelloWorld.php';
class HelloWorldTest extends PHPUnit_Framework_TestCase
{
public function testHelloWorld()
{
$hw = new HelloWorld();
$greeting = $hw->get();
$this->assertEquals('moin', $greeting);
}
}
?>
Here is the HelloWorld class:
<?php
class HelloWorld {
private $greeting;
public function __construct() {
$this->greeting = "moin";
}
public function get() {
return $this->greeting;
}
}
If invoked like this:
/mnt/workspace/monza/zero/zero php phpunit.php UnitTest HelloWorldTest.php
the test case runs successfully. It also runs if the word 'UnitTest' is ommitted. It is a little bit slow to invoke.
Structuring tests and source code
In an Eclipse project it's normal to put source code under an src/ directory and then put the equivalent test cases under tests/, usually laid out in the same way as the source tree. For sMash projects the most convenient layout is to have the tests in a separate sMash project which depends on the project which contains the source code.
To make one project depend on another it is necessary to make a change to the ivy.xml file in the dependent project. There should be a line like this in the ivy.xml file of the parent project:
<info module="AProject" organisation="zero" revision="1.0.0">
The line in the ivy.xml file of the dependent project should go inside the dependencies section and should look like this:
<dependency name="AProject" org="zero" rev="1.0.0"/>
The correspondence between the two lines is fairly clear. Saving the ivy.xml file should initiate a zero resolve.
In order to run tests the test project also has to depend on a phpunit project. The relationship between the projects is indicated below:

Relationship between source, tests and phpunit projects
The red text indicates new or modified files in each project. The additions made to the phpunit project to get PHPUnit to run on Zero were discussed above. Two new projects have been created, called AProject and AprojectTests. A file called HelloWorld.php has been created in the app/scripts directory of AProject. The contents of the
<?php
/**
* HelloWorld
*
* Simple greeting class
*
* @category Testing
* @package PHPUnitTesting
* @author Zoe Slattery <zoe@php.net>
* @copyright IBM
* @license
*
*/
Class HelloWorld {
private $greeting;
public function __construct($greeting)
{
$this->greeting = $greeting;
}
public function getGreeting()
{
return $this->greeting;
}
}
?>
A matching test class has been created in the app/scripts directory of the project AProjectTests. The contents of that class are:
<?php
/**
* HelloWorldTest
*
* Test for simple greeting class
*
* @category Testing
* @package PHPUnitTesting
* @author Zoe Slattery <zoe@php.net>
* @copyright IBM
* @license
*
*/
include 'HelloWorld.php';
class HelloWorldTest extends PHPUnit_Framework_TestCase
{
public function testHelloWorld()
{
$class = new HelloWorld('hello');
$greeting = $class->getGreeting();
$this->assertEquals('hello', $greeting);
}
}
?>
To run the HelloWorldTest.php test class from the command line simply change directory to AProjectTests/app/scripts and type
/path/to/my/zero/install/zero php phpunit.php UnitTest HelloWorldTest.php
This is still a bit tedious because we have to explicitly include the class that we are testing in the test script. It would be better to do it using an autoloader. In fact this turns out to be very easy. I created a file called Autoload.php in the app/scripts directory of AProject. The contents of the file look like this:
<?php
function __autoload($className) {
include $className . ".php";
}
?>
Now I can replace including a specific class in each test with the following line:
This assumes there there is always one class in a file and the file name is the same as the class name with a '.php' on the end. It would be possible to make a slightly more complicated AutoLoad class that used a ClassMap to deal with more complicated relationships between files and class names, but having one class per file is generally good practice so AutoLoad does not need to be more complicated.
Single unit tests can also be run using sMash in Eclipse. PHPUnit needs to be set up as an external tool, the external tool configuration screen looks like this:

External tool configuration for PHPUnit
The "Location" is the location of your installation of the 'zero' command, the "Working Directory" is the name of the project in which the test cases can be found (in this example it would be AProjectTests) and the 'Arguments' are the command line arguments for the zero command.
Make sure that the test name is highlighted and then click on run->external tools->PHPUnit to run the test
Running directories of tests
PHPUnit is designed to be able to run all the tests in a directory, the command to do this should be:
/path/to/my/zero/install/zero php phpunit.php scripts
if the tests are under the scripts directory. This doesn't work right just now because there is no implementation of RecursiveDirectoryIterator in Project Zero.
-- zoe - 21 May 2009