UnitTesting PHP
Once you've discovered the advantages of unittests you'll never want to write one single line of code without a test for it (well allmost ;)). You'll become "test-infected" :).
A few months ago, while doing a project in .NET, I discovered these advantages. Having unittests for your code helps you to refactor your code and add new/modified features to your application without having to fear that you'll break your code. Ofcourse you can still break your code, but if you have good unittests you'll immediately notice that you broke something and, depending on how good your tests are, you will also know where you broke something. When you have UnitTests you'll feel a lot safer when touching your code.
Today allmost every language has one or more unittesting frameworks. Most of them are based on JUnit, and are called xUnit frameworks. One example is NUnit, which is the JUnit port to .NET. Also PHP has it's unittesting frameworks, of which PHPUnit and SimpleTest are the best known.
SimpleTest is not just an xUnit framework. Apart from the classic TestCase and assert-methods it also offers support for Mock-objects and Stubs, webpage testing to load webpages and verify them, testing forms, authentication tests and a scriptable browser.
To illustrate it a bit, i'll give a, rather dumb, example. Suppose you create some Calculator
class, which has a method 'multiplyByTwo($number)
':
<?php
/**
* a KISS calculator.
*/
class Calculator {
/**
* This method takes a number and multiplies it by 2.
* @param int $number the number
* @return int the multiplied number
*/
function multiplyByTwo($number) {
return $number * 2;
}
}
Now you want to ensure that your multiplyByTwo
-method works. Therefore you write a unittest:
<?php
class TestCalculator extends UnitTestCase {
/**
* The calculator under test.
*/
var $_calculator;
/**
* This method is run before every test, and can be used to
* prepare the environment.
*/
function setup() {
$this->_calculator = new Calculator();
}
/**
* This method is run after every test and can be used to clean
* the environment.
*/
function teardown() {
// nothing to tear down curretly. An example could be to
// close a database connection
}
/**
* Tests the multiplyByTwo method. (this is the actual test)
*/
function testMultiplyByTwo() {
$result = $this->_calculator->multiplyByTwo(5);
$this->assertEqual(10, $result);
}
}
Explanation: You see three methods in the testclass:
setUp()
: This method is executed before every testmethod and can be used to prepare your environment. It is very likely that we will add more methods to our calculator which we will also have to test. Therefore we use thesetUp()
-method to create an instance of Calculator, so that this is automatically done for every test in the testclass.tearDown()
: is the same assetUp()
but after the testmehod. This can be used to cleanup the environment.testMultiplyByTwo()
: This is the actual test. By convention it is named 'test' followed by a name which describes what the method tests.
What happens in testMultiplyByTwo
is the following: First we invoke the multiplyByTwo
method on the calculator instance, which was automatically created by the setUp()
-method, and store the result in $result. Because we give 5 as the method's parameter we know the result should be 10, if the method works as expected. This expectation is tested with the assertEqual
method, which takes an expected value (10) and the actual result ($result). As an optional parameter it takes a string in which you can explain your expectation, it will be printed when the test fails and can help you determine what went wrong. The assertEqual method then verifies if both values are equal. If so the test passes, if not your test failes and you know you have a bug in your code! ofcourse there are a lot more assert
-methods, like assertNotNull
, assertTrue
, assertIsA
and so on.
To run your test you can use the following code:
<?php
$test = &new TestCalculator();
$test->run(new HtmlReporter());
If your code works (which is very likely in this example :) ), you'll get a nice green bar, telling you how many tests succeeded. However as soon as one or more tests fail you get an ugly red bar screaming for you attention and telling you how many, and more important, which, tests failed. You can try this by changing the '2' inside multiplyByTwo
in 3 and enjoy the red bar.
I hope this example has illustrated that you can sleep on both ears if you have enough tests to cover all your code and you keep the bar green :)
Comments
There are no comments.