About the Author

Chris Shiflett

Hi, I'm Chris, a web developer and a founding member of Analog. I live and work in Brooklyn, NY.


Test::Simple for PHP

Via PHPDeveloper.org, I just read a post on PhpGirl that discusses a familiar topic, testing:

I'll write a Test::Simple for PHP. Yes, I know there exists one already that uses the power of Perl to test PHP files, but I didn't have time to figure out how to set that up and probably won't be able to use Perl anyways on the production system.

A few years ago, Geoff Young and I gave a talk called Testing PHP with Perl. We thought we were being funny (in our defense, those who listened to the talk seemed to agree), but I think all we did is make our project seem inaccessible to PHP developers. Perl is scary. :-)

Part of our project is a pure PHP implementation of Test::More called test-more.php. If you want to really keep things dirt simple (which seems to be Nola's goal), you can use it by itself with no framework, but more on that in a minute.

In a follow-up post, Nola describes how she uses her simple testing library. The first argument to ok() is a boolean that indicates whether the test passes. She demonstrates some tests using conditionals that compare two values expected to be equal:

<?php 

$t
->ok($user->getRealName() == 'John Doe Test''get RealName');
$t->ok($user->getUserName() == 'jdoe''get UserName');
$t->ok($user->getEmail() == 'john@doe.com''get Email');
$t->ok($user->getPermission() == 1'get Permission');

?>

She also demonstrates some tests using conditionals that compare two values expected to not be equal:

<?php 

$t
->ok($user->getRealName() != 'Susie Doe''Not Realname Suzie Doe');
$t->ok($user->getUserName() != 'sdoe''Not Username sdoe');
$t->ok($user->getEmail() != 'suz@doe.com''Not email suz@doe.com');
$t->ok($user->getPermission() != 0'Not Permission 0');

?>

You can do the same sort of thing with test-more.php:

<?php 

include './test-more.php';
include 
'./user-class.php';

plan(8);

ok($user->getRealName() == 'John Doe Test''get RealName');
ok($user->getUserName() == 'jdoe''get UserName');
ok($user->getEmail() == 'john@doe.com''get Email');
ok($user->getPermission() == 1'get Permission');

ok($user->getRealName() != 'Susie Doe''Not Realname Suzie Doe');
ok($user->getUserName() != 'sdoe''Not Username sdoe');
ok($user->getEmail() != 'suz@doe.com''Not email suz@doe.com');
ok($user->getPermission() != 0'Not Permission 0');

?>

I created a simple user-class.php file to implement the methods she uses:

<?php 

class user
{
    public function 
getRealName() { return 'John Doe Test'; }
    public function 
getUserName() { return 'jdoe'; }
    public function 
getEmail() { return 'john@doe.com'; }
    public function 
getPermission() { return 1; }
}

$user = new user;

?>

If you just run this PHP script, you'll see the raw TAP output:

1..8
ok 1 - get RealName
ok 2 - get UserName
ok 3 - get Email
ok 4 - get Permission
ok 5 - Not Realname Suzie Doe
ok 6 - Not Username sdoe
ok 7 - Not email suz@doe.com
ok 8 - Not Permission 0

If a test fails, the last line lets you know about it (in addition to one of those lines being not ok instead of ok):

# Looks like you failed 1 tests of 8.

So, even without a testing framework, you can use test-more.php as a simple testing facility. If you want to try it yourself, you can download Apache-Test (it's bundled with the distribution), look at the very bottom of TestConfigPHP.pm, or grab it from my code repository:

P.S. Using Test::Harness To Test PHP Applications, a talk being given at PHP Quebec, is supposed to cover this same topic. Hopefully Ken is keeping up with what's going on. If so, it should be a good talk. If not, it will be disappointing. :-)

About This Post

Test::Simple for PHP was posted on Thu, 26 Jan 2006 at 16:33:01 GMT.

6 Comments

1. Nola's GravatarNola said:

I looked all over for where I could download test-more.php after reading your presentation. Finally (I almost emailed you too!) yesterday when I was trying to get TestConfigPHP working, I found it. I also got Andy Lester's version last night.

I still think I'd rather have it in a class. Having global variables gives me jitters and I like having my "namespace" in my class :) though it would be unlikelly that I would ever have another function called "ok" (etc) in my code.

Interesting using the "register_shutdown_function" never used that before. Thats better than my $t->report(); which today when I was working with it forgot to add it to one of my test files and I was wondering why it didn't spit out the report.

Thanks for the "history" and information.

Thu, 26 Jan 2006 at 18:32:25 GMT Link


2. Chris Shiflett's GravatarChris Shiflett said:

Yeah, Geoff and I have been discussing how to make this stuff more accessible. Not being able to get test-more.php by itself is a problem, which is why I just added a link to it as a temporary solution. We'll probably find a more official way to distribute it soon.

I think your post highlights why this little testing library can be useful. The complex testing libraries like Simple-Test and PHPUnit are great, but neither seem to follow the "PHP way" of keeping things simple. Using test-more.php is easy, and it also provides a nice upgrade path to Apache-Test when you need a more sophisticated testing framework. (To be fair, both Simple-Test and PHPUnit now also offer Apache-Test integration.)

Regarding functions in the global namespace, I can understand your hesitation. But, those who dislike such things are the ones least likely to encounter a collision, right? :-)

Anyway, glad to see someone else in the PHP community interested in testing. Thanks for helping to spread the word.

Thu, 26 Jan 2006 at 18:46:05 GMT Link


3. Pedro Cardoso's GravatarPedro Cardoso said:

I think that the folowing does the same thing.

I am using it in a personal project and think it is a great tool.

It is class bases and the library is quite extensive.

Probably you all know about it but anyway, here it is:

http://www.lastcraft.com/

Regards

JP

Fri, 27 Jan 2006 at 09:58:08 GMT Link


4. Matt's GravatarMatt said:

Why not atleast create an class that could act as a namespace, and could also be instantiated thereby eliminating the globals? That seems like a good next step?

-matt

Wed, 22 Mar 2006 at 21:08:58 GMT Link


5. Chris Shiflett's GravatarChris Shiflett said:

Hi Matt,

I might do that, but people can always encapsulate this in a class themselves, as Nola has demonstrated.

The original intention was for the behavior to act as closely to Test::More as possible, and its success might be due to its extreme simplicity.

On the other hand, I do see the benefits of offering a class for this, one being that I could add it as a PEAR component.

Wed, 22 Mar 2006 at 21:14:17 GMT Link


6. Matt's GravatarMatt said:

Hey Chris, another thing that would be nice (if it were in a class) is to not print directly from each function, but to append the html/text to a variable and then do a report after it's done, printing the variables' content instead. That way, you could even use a seperate logger class (for example) and email the tests. I guess this could just be done with output buffering before the tests, but it'd be nice if it were built in. I understand that this is suppossed to be just like the perl version though. Anyway, I'm actually testing now! For the first time. :)

Thu, 23 Mar 2006 at 12:45:30 GMT Link


Post A Comment

Personal Details and Comment

Style Guide

Line breaks are converted to paragraphs. Also use:

  • <a href="" title="">text</a>1
  • <em>text</em>
  • <blockquote><p>text</p></blockquote>
  • <code>2  <?php  if ($foo) {      $foo = TRUE;  }  ?></code>
  1. Note: <code> can be used inline (e.g. in paragraphs) or in a block as shown. Include whitespace and newlines in blocks.

Please enter Chris (my first name) below. This is a primitive spam prevention technique, and I apologize for the inconvenience.

Preview and Submit

Upcoming Talks

ConFoo

10 - 12 Mar 2010

At Hilton Montréal Bonaventure, Montréal, Canada.

South by Southwest

12 - 16 Mar 2010

At Austin Convention Center, Austin, Texas.

Dutch PHP Conference

10 - 12 Jun 2010

At TBD, Amsterdam, Netherlands.

O'Reilly Open Source Convention

19 - 23 Jul 2010

At Oregon Convention Center, Portland, Oregon.

New Comments

Niall Kelly wrote:

Having tried other methods without success and looked through plenty of bloated documentation, th...

Posted in Git on Snow Leopard
liukang wrote:

I have problem with this example. In my php.ini magic_quotes_gpc is off so i'm using only addsla...

Posted in addslashes() Versus mysql_real_escape_string()
RyanTheGreat wrote:

Well, I'm not Chris, but I will do my best to address the questions raised in the comments by Ian...

Posted in Security Corner: Cross-Site Request Forgeries
Chris Shiflett wrote:

Thanks for the kind words, Simon. I'm glad you liked the tutorial. In case it's helpful, here'...

Posted in Webstock
Chris Shiflett wrote:

Hi Robin, I plan to post something about it, but it's going to be hard to express everything i...

Posted in Webstock

Browse Comments


Work and Books

Analog Essential PHP Security HTTP Developer's Handbook