Individual PHP class testing

Posted by wintellect on Mon, 8 Feb 2010 - 09:57

Up until recently I have avoided learning OOP. I have had no real drive or need to. In fact, most of the code I worked on seemed pretty procedural and so OOP was never actually on the table. However, I have now started  my venture in OOP and am beginning to like what I see. Certainly one of the advantages I have noticed is how modular and portable it can make the code. Having written one class in a file, I merely need to import the file from within another application to reap the benefits of the previous hard work. The code is self-contained and only relates to the class. This led me to think about testing classes.

My most recent work has been to write a BBCode class. Upon discussing my efforts and an issue (related to regular expression greediness) with andre, he suggested I write a script to test the class. This made sense to me and really showed the beauty of classes. My test script needed only import the class and issue the appropriate commands. It meant that no other code was disturbed and no other code could impact the results of my class. Here's what I came up with:

<?php
    include_once("bbcode.php");
    $tests = array(
        array('Bold', '[b]text[/b]', '<p><strong>text</strong></p>'),
        array('Italic', '[i]text[/i]', '<p><em>text</em></p>'),
        array('Underline', '[u]text[/u]', '<p><span style="text-decoration:underline">text</span></p>'),
        array('Line-through', '[s]text[/s]', '<p><span style="text-decoration:line-through">text</span></p>'),
        array('Font size', '[size=18]text[/size]', '<p><span style="font-size:18px">text</span></p>'),
        array('Font color', '[color=#123DEF]text[/color]', '<p><span style="color:#123DEF">text</span></p>'),
        array('Center text', '[center]text[/center]', '<p><div style="text-align:center">text</div></p>'),
        array('Quote', '[quote]text[/quote]', '<p><div class="comment_quote">text</div></p>'),
        array('Quote (named)', '[quote=person]text[/quote]', '<p><div class="comment_quote"><div class="comment_quote_name">person wrote:</div>text</div></p>'),
        array('Link', '[url]text[/url]', '<p><a href="text">text</a></p>'),
        array('Link (named)', '[url=location]text[/url]', '<p><a href="location">text</a></p>'),
        array('Image', '[img]text[/img]', '<p><img src="text" alt="" /></p>'),
        array('Image (resized)', '[img=99x45]text[/img]', '<p><img src="text" width="99" height="45" alt="" /></p>'),
        array('List (unordered)', '[ul][li]text[/li][li]more[/li][/ul]', '<p><ul><li>text</li><li>more</li></ul></p>'),
        array('List (ordered)', '[ol][li]text[/li][li]more[/li][/ol]', '<p><ol><li>text</li><li>more</li></ol></p>'),
        array('Nested tags', '[b][i]text[/i][/b]', '<p><strong><em>text</em></strong></p>'),
        array('Image link', '[url=location][img]text[/img][/url]', '<p><a href="location"><img src="text" alt="" /></a></p>'),
        array('Image link text', '[url=location]text[img]src[/img][/url]', '<p><a href="location">text<img src="src" alt="" /></a></p>'),
        array('Miss close tag', '[b]text', '<p>[b]text</p>'),
        array('Miss open tag', 'text[/b]', '<p>text[/b]</p>'),
        array('Extra close tag', '[b]text[/b][/b]', '<p><strong>text</strong>[/b]</p>'),
        array('Extra open tag', '[b][b]text[/b]', '<p><strong>[b]text</strong></p>'),
        array('Non-existent tag', '[bold]text', '<p>[bold]text</p>'),
        array('Half tag', '[btext[/b]', '<p>[btext[/b]</p>'),
    );
    echo "Running : " . count($tests) . " tests\n\n";
    $num = 1;
    foreach ($tests as $t) {
        printf("- TEST %02d --- %-18s ---------------------\n", $num, $t[0]);
        $remark = new bbcode($t[1]);
        $actual = $remark->getComment();
        echo "Sample : " . $t[1] . "\n";
        echo "Expect : " . $t[2] . "\n";
        echo "Actual : " . $actual . "\n";
        if ( $t[2] === $actual )
            echo "Status : PASS\n";
        else
            echo "Status : FAIL\n";
        echo   "------------------------------------------------------\n\n";
        $num++;
    }
?>

Essentially the array $tests is my list of tests, each entry is an array containing the test name, the text to be tested and the expected outcome. Following that is a loop which works its way through the test array, runs the test and confirms if it was a pass or a test. Running the test results in the following output:

$ php test_bbcode.php
Running : 24 tests

- TEST 01 --- Bold ---------------------
Sample : [b]text[/b]
Expect : <p><strong>text</strong></p>
Actual : <p><strong>text</strong></p>
Status : PASS
------------------------------------------------------

- TEST 02 --- Italic ---------------------
Sample : [i]text[/i]
Expect : <p><em>text</em></p>
Actual : <p><em>text</em></p>
Status : PASS
------------------------------------------------------

...

This could further be reduced to displaying only the numer of FAILS in test cases:

$ php test_bbcode.php | grep FAIL | wc -l
0

Furthermore, the process also caters for changes to the class as new test cases merely require addition to the $tests array.

Now I have a fully automated set of scripts to check any code changes I make to the BBCode module. It's a neat thing in that my class is file used for testing is the exact same file that is used in the application itself. There is no need to copy code or strip it from the midst of other segments of code. There is also no way that other classes or procedural code can impact my testing of this class.

 


 

Add Comment
BBCode supported - HTML will not work!

Text browser users please type in the number 77 followed immediately by the answer to five minus two - use NO spaces
The graphic contains six lowercase letters, enter them in the order they appear without spaces