Showing posts with label tutorial. Show all posts
Showing posts with label tutorial. Show all posts

Wednesday, August 13, 2008

CakePHP 1.1 Unit Testing Test Suite v 1.0.0.5 tutorial

So your stuck with CakePHP 1.1, but you need to add Unit Testing, what do you do?


You can grab Cake Test Suite v1.0.0.5 (using SimpleTest) here


The thing with this Test Suite is that I couldn't find documentation anywhere so I decided to write this little tutorial on how to get started.


Step 1: Setup
First make sure your CakePHP Project's debug level is set to at least 1.


Next, after unzipping the app folder into your project and trying to run the test controller(http://yourproject/test/) you might see that you will get this error:


Notice: Use of undefined constant CORE_PATH - assumed 'CORE_PATH' in D:\Flex Workspaces\cakeamfphp\cake\config\paths.php on line 44



To fix this open up /app/webroot/test/index.php and insert this on line 82:

if (!defined('CORE_PATH')) {
if (function_exists('ini_set')) {
ini_set('include_path', CAKE_CORE_INCLUDE_PATH . PATH_SEPARATOR . ROOT . DS . APP_DIR . DS . PATH_SEPARATOR . ini_get('include_path'));
define('APP_PATH', null);
define('CORE_PATH', null);
} else {
define('APP_PATH', ROOT . DS . APP_DIR . DS);
define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS);
}
}

require CORE_PATH.'cake'.DS.'bootstrap.php';


Step 2: Writing the Tests

Lets say for example, I have a model user.php that I want to test, I have to create this file as /app/tests/app/cases/models/User.test.php

It will look something like this:


class UserTest extends UnitTestCase {

function testSomething() {
loadModel('User');
$user = &new User();
$this->assertEqual($user->name, 'User');
}
}

?>



If testing a controller, you would want to use the loadController method.


If I wanted to make a group test of my models I would for example make a file
in app/tests/app/groups/Model.group.php:



require_once(TESTS.'/app/cases/models/User.test.php');
require_once(TESTS.'/app/cases/models/User_Builder.test.php');

class ModelTest extends GroupTest {

function ModelTest(){
$this->addTestCase(new UserTest());
$this->addTestCase(new User_BuilderTest());
}

}

?>





Hope this helps get you on the right track. Take a look at the simpletest docs for more information on how to unit test your project.

Thursday, July 10, 2008

PureMVC Pipes - using the filter

The filter is useful for filtering the messages going through the pipes. An analogy you can use is a water filter.


wall ======== [water filter] ========= fridge/sink
pipe1 pipe2



in code form this would look like this:


// create output pipes 1
var pipe1:IPipeFitting = new Pipe();
var pipe2:IPipeFitting = new Pipe();

// create filter
var filter:Filter = new Filter( 'TestFilter' );

// connect input fitting
var connectedInput:Boolean = pipe1.connect( filter );

// connect output fitting
var connectedOutput:Boolean = filter.connect( pipe2 );




the way something gets filtered is this..

1] the message going through the filter must have a variable in the message header,
lets call it particleSize:int.

example:


var h20Message:IPipeMessage = new Message( Message.NORMAL, { particleSize:1, name:'h20'} );
var mineralMessage:IPipeMessage = new Message( Message.NORMAL, { particleSize:10, name:'mineral'} );


2] the filter also needs a paramater to compare wether to let the message through or not, lets call it maxParticleSize.

3] then the filter needs a filter function which checks if the maxParticleSize >= particleSize.


How to setup the filter

to make it do something we have to create the filter and pass in parameters to the constructor.


/**
* Constructor.
*


* Optionally connect the output and set the parameters.


*/
public function Filter( name:String, output:IPipeFitting=null, filter:Function=null, params:Object=null )
{
super( output );
this.name = name;
if ( filter != null ) setFilter( filter );
if ( params != null ) setParams( params );
}


One way to create the filter is to pass in all name, output, filter and params to the functions parameters:


var teeMerge:TeeMerge = new TeeMerge();
var filter:Filter = new Filter( 'waterFilter',
new PipeListener(this,function ( message:IPipeMessage ){trace('particle got through');),
function( message:IPipeMessage, params:Object ):void { if (message.getHeader().particleSize >= params.maxParticleSize) throw new Error('particle filtered'); },
{ maxParticleSize:5 }
);
teeMerge.connect(filter);
junction.registerPipe( PipeAwareModule.STDIN, Junction.INPUT, teeMerge );


above, messages enter input the teeMerge, then goes to the filter, if the filter
accepts the message, it sends it to the pipelistener.



If you look at the Filter constructor you can see output, filter and params are optional and can be set/modified after creation of the filter which I will explain how that works below.

setting the output
filter.connect(a IPipeFitting)

setting the log level/filter function
If you look at Filter's source, its write method is where the filter changes it's log level and filter function. When the filter sees a FilterControlMessage.SET_PARAMS it will then try to set the new params.

below I set the maxParticleSize to 10 because i want the mineral to go through:


var maxParticleSize:number = 10;
var setLogLevelMessage:LogFilterMessage = new LogFilterMessage(FilterControlMessage.SET_PARAMS, particleSize);
filter.write(setLogLevelMessage );


of course, you can send the FilterControlMessage through a modules junction to the
filter using junction.sendMessage as well.