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

Integration test 2

Unit test 1

Unit test 2

Unit test 3

Unit test 4

Code

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/ unit/ fixtures/ phpunit.xml bootstrap.php main directory for all tests unit tests directory fixtures directory main phpunit config file 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) { $this->_imageSrc = $data; } public function getImageSrc() { return $this->_imageSrc; } //... } } } //... // 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 );

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(); if ($expectedImgSrc !== null) { $model->imageSrc = $expectedImgSrc; } $this->assertEquals( $expectedImgSrc, $model->imageSrc ); } //... } //... /** * Data Provider for getImageSrc / setImageSrc * * @return array */ public function imgSrcDataProvider() { return array( array(null), array('some random text'), array(0), array(-1) ); }

//...

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