Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

petdance (2468)

AOL IM: petdance (Add Buddy, Send Message)
Yahoo! ID: petdance (Add User, Send Message)

I'm Andy Lester, and I like to test stuff. I also write for the Perl Journal, and do tech edits on books. Sometimes I write code, too.

Journal of petdance (2468)

Wednesday August 20, 2003
11:23 AM

Test::More with PHP

[ #14227 ]
At Monday's Chicago Perl Mongers meeting, I talked to Jason Gessner about faking the Perl Test::Harness protocol in other languages. He asked for the PHP module that I wrote to do it for PHP. Here it is:


$_test_ntests = 0;
$_nfailures = 0;
$_ended = 0;
$_no_plan = 0;

register_shutdown_function( '_test_for_ending' );

function ok( $condition, $name = '' ) {
    global $_test_ntests;
    global $_nfailures;

    if ( !$condition ) {
        print "not ";
    print "ok $_test_ntests";
    if ( $name != "" ) {
        print " - $name";
    print "\n";

    return $condition;

function pass( $name = '' ) {
    return ok( TRUE, $name );

function fail( $name = '' ) {
    return ok( FALSE, $name );

function skip( $msg, $num ) {
    for ( $i=0; $i<$num; $i++ ) {
        pass( "# SKIP $msg" );

function is( $actual, $expected, $name = '' ) {
    $ok = ($expected == $actual);
    ok( $ok, $name );
    if ( !$ok ) {
        diag( "Expected \"$expected\"" );
        diag( " but got \"$actual\"" );
    return $ok;

function isnt( $actual, $dontwant, $name = '' ) {
    $ok = ($actual != $dontwant);
    ok( $ok, $name );
    if ( !$ok ) {
        diag( "Didn't want \"$actual\"" );
    return $ok;

function isa_ok( $object, $class, $name = null ) {
    if ( isset( $object ) ) {
        $actual = get_class( $object );
        if ( !isset( $name ) ) {
            $name = "Object is of type $class";
        return is( get_class( $object ), strtolower( $class ), $name );
    } else {
        return fail( "object is undefined" );

function like( $string, $regex, $name='' ) {
    return ok( preg_match( $regex, $string ), $name );

// We diag() to stderr instead of stdout like Perl does.  It shouldn't
// make any difference to the harness.
function diag( $lines ) {
    if ( is_string( $lines ) ) {
        $lines = split( "\n", $lines );
    foreach ( $lines as $str ) {
        print "# $str\n";

function plan( $ntests ) {
    print "1..$ntests\n";

function no_plan() {
    global $_no_plan;

    $_no_plan = 1;

function test_end() {
    global $_no_plan;
    global $_test_ntests;
    if ( $_no_plan ) {
        print "1..$_test_ntests\n";

    global $_ended;
    $_ended = 1;

    $ver = phpversion();
    if ( version_compare( $ver, '4.2.2' ) > 0 ) { # >4.2.2?
        global $_nfailures;
        exit( $_nfailures > 254 ? 254 : $_nfailures );
    } else {
        # Don't return anything

function html_ok( $str, $name = "" ) {
    $fname = tempnam( getenv("TMP"), 'lint-' );
    $fh = fopen( $fname, "w" );
    fwrite( $fh, $str );
    fclose( $fh );

    $results = Array();
    $results = shell_exec( "weblint $fname" );
    unlink( $fname );

    if ( $results ) {
        $ok = fail( $name );
        diag( $results );
    } else {
        $ok = pass( $name );
    return $ok;

function _test_for_ending() {
    global $_ended;
    if ( !$_ended ) {
        fail( "Didn't call test_end()" );


Note that html_ok() is from Test::HTML::Lint.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.
  • Testing Protocol (Score:3, Interesting)

    by Ovid (2709) on 2003.08.20 11:33 (#23333) Homepage Journal

    You know, this looks like you're well on your way to creating the testing protocol that was discussed. By distributing a set of standard tools in various languages, one can implement the protocol rather than wait for people to adopt the proposal. That could be a sneaky end run around a lot of common objections.

    And since I had already started writing testing software for Python [] that mirrors Test::More, it looks like we could get a jump on that, too. Of course, there are those who suggest the more traditional FooUnit type of frameworks. Since I'm less familiar with those, I don't know if they're a better option or not (though they are more common).

  • Test::More w/ PHP (Score:3, Interesting)

    by inkdroid (3294) on 2003.08.20 11:47 (#23336) Homepage Journal

    Would it be outlandish to have the Test::More distro actually include foreign language (non-Perl) files which would generate suitable output suitable for Test::Harness?

    Having these could leverage Perl as general purpose testing language since it would allow you to have a single test suite that tested code in Perl *and* PHP, Python, Java (etc).

    These hypothetical TestMore.php and files could live in a subdir of the distro, and not get installed with the other .pm files during make install.

  • I've been using a PL/SQL package I made called T to do this, sort of. Probably not complex enough to interface with Test::Harness, yet.

    Even though Perl isn't a part of my job description any more, the things I have learned and continue to learn through the Perl community still help me constantly.

    J. David works really hard, has a passion for writing good software, and knows many of the world's best Perl programmers
  • well, I started on the VB.NET interface based on the PHP file posted (many thanks, Andy!). is and like are not valid function names in VB.NET, but i may preface the testing functions with vb_ anyway, so that should be ok.

    when i get something other than an empty shell that produces no build errors, I will post it up for comments.
  • Me too! (Score:2, Interesting)

    The Test::Harness protocol is one of the things I like most about Perl's testing framework.

    In a recent job I had a bunch of code with tests written in C. Quick hack to output the approriate "ok" and "not ok" lines and I have instant integration with the rest of the test suite. Very nice.
    • I thought that cross language testing frameworks are already reality, as seen on The other place where Test::Harness is used for testing a bunch of languages is in the Parrot project.
      /* */
      • Afraid not. The various xUnit frameworks don't support multiple languages - they're just the same framework (class hierarchy wise) implemented in several different languages. For example, you can't analyse Smalltalk test results in JUnit or Java test results in SUnit.

        What the xUnit frameworks lack is a language independent way of communicating test results to the test runner. Perl has the Test::Harness protocol. As long as the test script outputs the appropriate "ok" / "not ok" lines it can be fed into Tes