You are on page 1of 20

13/06/2013 - Yii London Meetup

PHP Unit Testing


in Yii
How to start with TDD in Yii
by Matteo 'Peach' Pescarin
Twitter: @ilPeach

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

What is this presentation about?

Quick introduction to TDD and Unit Testing


How to Unit Test? Types of Tests
PHPUnit and Yii
Write tests and Database interactions
Fixtures
Other features
Command line use
Few links.

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Test Driven Development (TDD)


"encourages simple design and inspires
confidence" - Kent Beck
Re-discovered in 2004, is related to the testfirst concept from eXtreme Programming.
Works with any Agile methodology, but can be
applied in any context.
Also useful when dealing with legacy code that
wasn't developed with such ideas in mind.
Used as a way to document code by examples.

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

What is Unit Testing?


It's not about bug finding (there's no way this
can be proved to be true).
It's about designing software components
robustly.
The behaviour of the units is specified through
the tests.
A set of good unit tests is extremely valuable!
A set of bad unit tests is a terrible pain!

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Some tips to write Unit Tests


They must be isolated from each other:
Every behaviour should be covered by one test.
No unnecessary assertions (TDD: one logical assertion
per test)
Test one code-unit at a time (this should force you write
non-overlapping code, or use IoC, Inversion of Control)
Mock external services and states (without abusing)
Avoid preconditions (although it might be useful
sometimes)

Don't test configuration settings.


Name your tests clearly and consistently.

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Types of tests
Functional test 1

Integration test 1

Unit test 1

Integration test 2

Unit test 2

Unit test 3

Code

Unit test 4

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Types of tests in MVC frameworks

Controllers/Views

Functional test 1

Integration test 1

Integration test 2

Models
Unit test 1

Unit test 2

Unit test 3

Unit test 4

The states and the dependencies in controllers/views makes unit testing completely useless from a
server-side point of view.
Not true when considering javascript testing and other front-end behaviour/functionality which can
be done in other ways

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Enters PHPUnit
PHPUnit help you deal with unit and
integration tests. http://www.phpunit.de/
Provides everything needed for any type of
test.
Produces reports in different formats (also for
code coverage).
Yii provides the functionality to integrate and
automate PHPUnit without worrying too much
about configuration.

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Configuring tests in Yii


Have PHPUnit installed and a Yii app ready.
Directory structure available:
protected/tests/

main directory for all tests

unit/

unit tests directory

fixtures/

fixtures directory

phpunit.xml

main phpunit config file

bootstrap.php

Yii related configuration

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Setup a test DB
In protected/tests/bootstrap.php :
$config=dirname(__FILE__).'/../config/test.php';

In protected/config/test.php :
'db'=>array(
'connectionString' => 'mysql:host=localhost;
dbname=myproject_test',
),

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Write your tests


Tests are made of
assertions
[see full list at phpunit.de]
// models/Doodle.php
class Doodle extends CActiveRecord
{
//...
private $_imageSrc = null;
public function setImageSrc($data)

// tests/unit/doodleTest.php
class DoodleTest extends DBbTestCase
{
//...
/**
* Test getImageSrc returns what
* has been passed to setImageSrc
*/
public function
testGetImageSrcRerturnsWhatHasBeenPassedToSetImageSrc() {
$model = new Doodle();
$expectedImageSrc = 'Something';
$model->imageSrc = $expectedImgSrc;

$this->assertEquals(
$expectedImgSrc,
$model->imageSrc
);

$this->_imageSrc = $data;
}
public function getImageSrc() {
return $this->_imageSrc;
}
//...
}

}
//...
}

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Testing all cases: DataProviders


// tests/unit/doodleTest.php
class DoodleTest extends DBbTestCase
{
//...

//...

/**
* Test getImageSrc returns what has been passed to
setImageSrc
*
* @dataProvider imgSrcDataProvider
*/
public function
testGetImageSrcRerturnsWhatHasBeenPassedToSetImageSrc(
$expectedImgSrc
) {
$model = new Doodle();

/**
* Data Provider for getImageSrc / setImageSrc
*
* @return array
*/
public function imgSrcDataProvider() {
return array(
array(null),
array('some random text'),
array(0),
array(-1)
);
}

if ($expectedImgSrc !== null) {


$model->imageSrc = $expectedImgSrc;
}
$this->assertEquals(
$expectedImgSrc,
$model->imageSrc
);
}
//...

//...
}

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Database Interaction and AR classes


Just load the project database structure.
Fill in the tables that will not change during the
tests.
Create and save objects as needed...
(this is normally not enough)
Objects that are loaded, modified and updated
from and to the database require the use of Yii
fixtures.

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Yii Fixtures
Flexible and useful way to deal with a mutable set of data.
Defined in protected/tests/fixtures/<lowercase-tablename>.php
Contains a return statement of an array of arrays.
Each first level array is a row. Each row can be key
indexed.
Setup at the top of the test Class with:
public $fixtures = array(
'users' => 'User', // <generic_name> => <table_name>
);

For every test in the class the fixtured tables will be


emptied and filled in with the data (this could be quite
expensive).

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Fixtures uses
Class UserTest extends CDbTestCase
{
public $fixtures = array(
'users' => 'User',
);
/**
* @dataProvider expectancyDataProvider
*/
public function testUserExpectancyReturnsTheExpectedValue(
$expectedExpectancyValue
) {
$user = new User();
$user->setAttributes($this->users['simpleUser']);
$this->assertEquals(
$expectedExpectancyValue,
$user->calculateUserExpectancy()
);
}

This is just an example on


how you can use the data
from the fixture array.
You can always load the
same data that has been
loaded into the table and use
that.
More examples provided in
the Yii Definitive Guide.

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Other important features


testing exceptions using
@expectedException <Exception>
Mocks and Stubs:
mock dependencies, injecting objects and resolve
dependencies
prepare stubs with methods that returns specific
values based on certain conditions

a lot more other stuff depending on your


needs.

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Command line invocation


test everything:
$ cd /path/to/project/protected/tests/
$ phpunit unit
PHPUnit 3.6.11 by Sebastian Bergmann.
Configuration read from /path/to/project/protected/tests/phpunit.xml
................................................................. 65 / 86 ( 75%)
.....................
Time: 01:02, Memory: 18.00M
OK (86 tests, 91 assertions)
$

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Command line invocation (2)


test a single file:
$ phpunit unit/CustomerTest.php
Time: 1 second, Memory: 15.00Mb
OK (32 tests, 37 assertions)

or a single test method using a pattern:


$ phpunit --filter testCustomerStartEndDates unit/CustomerTest.php
Time: 1 second, Memory: 15.00Mb
OK (32 tests, 37 assertions)

for more info there's always


$ phpunit --help

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

More information and resources


Specific to PHPUnit and Yii Unit Testing
PHPUnit manual
http://phpunit.de/manual/current/en/index.html
Yii Guide on testing
http://www.yiiframework.com/doc/guide/1.1/en/test.overview

Generic information on TDD


Content Creation Wiki entry on TDD: http://c2.com/cgi/wiki?
TestDrivenDevelopment
Software Development Mag
http://www.methodsandtools.com/archive/archive.php?id=20

PHP Unit Testing in Yii - 13/06/2013 - Yii London Meetup

Thank you!

Make a kitten happy and start testing today!

You might also like