Unit tests are written to provide the developer with verification that the code is doing the right things.
This tests focus on the smallest units within a software application. In an object-oriented application, (such as a Yii web application) the smallest units are the public methods that make up the interfaces to classes. Unit tests should focus on one single class, and not require other classes or objects to run. Their purpose is to validate that a single unit of code is working as expected.
Basic conventions and steps for writing tests with PHPUnit:
1. The tests for a class Abc go into a class AbcTest.
2. AbcTest inherits (most of the time) from PHPUnit_Framework_TestCase.
3. The tests are public methods that are named test*.
4. Inside the test methods, assertion methods such as assertEquals() are used to assert that an actual value matches an expected value.
Writing Tests for PHPUnit in Yii:
A unit test in Yii is written as a PHP class that extends from the framework class, CTestCase. The conventions prescribe it be named AbcTest where Abc is replaced by the name of the class being tested. For example,
if we were to test MyClass, we would name the test class MyClassTest. This class is saved in a file called MyClassTest.php under the folder protected/tests/unit/. The test class primarily has a set of test methods named testXyz where Xyz is often the same as the method name the test is built for in the class being tested. Continuing with the MyClassTest example, if we were testing our Helloworld() method, we would name the corresponding test method in our MyClassTest class, testHelloworld().
For those testing, Create the new file, protected/tests/unit/MyClassTest.php and add to it the following code:
class MyClassTest extends CTestCase {
public function testHelloworld() {
$this->assertTrue(true);
}
}
Run phpunit tests in Command-Line:
The PHPUnit command-line test runner can be invoked through the phpunit command.
Now we can navigate to our tests folder and execute the command to run this test:
%cd /WebRoot/demo/protected/tests
%phpunit unit/MyClassTest.php
Test Result:
[khaled@folsom tests]$ phpunit unit/MyClassTest.php
PHPUnit 3.5.12 by Sebastian Bergmann.
.
Time: 0 seconds, Memory: 4.00Mb
OK (1 test, 1 assertion)
For each test run, the PHPUnit command-line tool prints one character to indicate progress:
. Printed when the test succeeds.
F Printed when an assertion fails while running the test method.
E Printed when an error occurs while running the test method.
S Printed when the test has been skipped.
I Printed when the test is marked as being incomplete or not yet implemented.
PHPUnit distinguishes between failures and errors. A failure is a violated PHPUnit assertion such as a failing assertEquals() call. An error is an unexpected exception or a PHP error. Sometimes this distinction proves useful since errors tend to be easier to fix than failures. If we have a big list of problems, it is best to tackle the errors first and see if we have any failures left when they are all fixed.
More help on phpunit can be found by typing ‘phpunit –help’ on command line.
Fixtures:
One of the most time-consuming parts of writing tests is writing the code to set the world up in a known state and then return it to its original state when the test is complete. This known state is called the fixture of the test.
PHPUnit supports sharing the setup code. Before a test method is run, a template method called setUp() is invoked. setUp() is where we create the objects against which we will test. Once the test method has finished running, whether it succeeded or failed, another template method called tearDown() is invoked. tearDown() is where we clean up the objects against which we tested.
Setting Fixture in Yii:
A test fixture is a system state or context in which tests are run. We want to run our tests a multiple number of times, and each time they run, we want to be able to have them return repeatable results. A fixture is intended to provide a well-known and fixed environment in which to run our tests. Typically, a fixture’s job is to ensure that all of the objects involved in the testing are consistently initialized to a particular state. One typical example of a fixture is the loading of a database table with a fixed and known set of data. Fixtures in yii are PHP files that return an array specifying the initial data configuration. They are typically named the same as the database table they represent, and are located under the protected/tests/fixtures/ folder.
Configuring the fixture manager:
Was actually already done for us when we created the initial application. If we open up the application configuration file specific to testing, protected/config/test.php, we will see the following application component defined:
'fixture'=>array( 'class'=>'system.test.CDbFixtureManager', ),
So the application has already been configured to use this fixture manager. We need to separate our development database from our testing database so that our testing will not continue to interfere with
our development.
return CMap::mergeArray(
require(dirname(__FILE__) . "/main.php"), array("components" => array(
"fixture" => array(
"class" => "system.test.CDbFixtureManager"
),
"db" => array(
"connectionString" => "mysql:host=localhost;dbname=eventapp_test",
"emulatePrepare" => true,
"username" => "test_username",
"password" => "test_password",
"charset" => "utf8'
),
),
)
);
We still need to tell our unit tests to actually use this fixture we just created. We do this in the unit test file. In this case, we will need to add our fixture declaration to the top of our test file protected/tests/unit/EventsTest.php as such:
public $fixtures = array('events' => 'Events');