JaggyGauran

Freelance developer, and designer

My CakePHP Testing Workflow

I've been a fan of Test Driven Development when it comes to Ruby on Rails.

Coming back to CakePHP, I've really had a hard time adjusting my work flow in terms of factories and testing and everything else. So, after researching a limited amount of resources for practices, conventions for implementing TDD on CakePHP, I just decided to make my own.

I made a factory builder for CakePHP. https://github.com/jaggyspaghetti/cakefactory

Structure

APP
| Test
|
|- Case
|-- Model
|--- RoleTest.php
|--- UserTest.php
|
|- Factory
|-- Role.json
|-- User.json

Here you can see all your factories are inside the Test/Factory folder.

Setup

Installation

Clone the application inside your Plugins folder

$ git clone https://github.com/jaggyspaghetti/cakefactory.git Factory

Load it and make sure you read the Plugin's bootstrap folder. Append this to your Config/bootstrap.php:

CakePlugin::load('Factory', array('bootstrap' => true));

Settings

The default location of your factories in the bootstrap here Plugin/Factory/Config/bootstrap.php

define('FACTORY', ROOT . DS . APP_DIR . DS . 'Test' . DS . 'Factory');

Setting up Factories

Factories are in json format, so there won't be much coding needed.

Let's say we have 2 models, User and Role. Here's how their factories would look:

Role.json

{
    "name":        "Administrator",
    "description": "Overall access to everything"
}

User.json

{
    "full_name": "Finn the Human",
    "username":  "finnthehuman",
    "password":  "adventure time!!!",
    "role_id": {
        "model": "Role",
        "attributes": {
            "name": "Adventurer"
        }
    }
}

Here you can see, you can add relations within the Factory and even override the attributes.

Testing Conventions

Factory::create($model, $attributes = array())

Create method bypasses all validations and inserts it straight to the database. I use this for testing valid factories just to see if the factory itself doesn't mess up with the database rules.

Factory::create('user', array('username' => 'jakethedog'));

Factory::build($model, $attributes = array())

This one returns the said model with overridden attributes.

$user = Factory::build('user', array('username' => 'iceking'));

Note

Objects returned by create and build are CakePHP Models, so you can reuse model functions like field(), read(), validates() and so on

Factory Validation

function testHasAValidFactory(){
    $factory = Factory::create('user');
    
    $this->assertNotEmpty($factory->read());
}

Validating Null Values

function testIsInvalidWithoutAUsername(){
    $user = Factory::build('user', array('username' => null));
    $this->assertFalse($user->validates());
}

Validating Duplicates

function testDoesNotAcceptDuplicateUsernames(){
    $username = Factory::create('user')->field('username');
    
    $user = Factory::build('user', array('username' => $username));
    
    $this->assertFalse($user->validates());
}