Skip to content

Testing

Mark edited this page Apr 1, 2014 · 27 revisions

Testing - best pratices with Cake2.x and PHPUnit3.7

Testing Controllers

In general it is best to only use testAction() once per test. My convention for the test method name is to use

"test" + "action name including prefix" + "method (if not default one)" + "optionally other pieces"
/**
 * testAdminAdd()
 *
 * @return void
 */
public function testAdminAdd() {
	$url = Router::url(array('admin' => true, 'controller' => 'users', 'action' => 'add'));
	$options = array(
		'return' => 'contents'
	);
	$result = $this->testAction($url, $options);
	$this->assertNotEmpty($result);
}

/**
 * testAdminAddPost()
 *
 * @return void
 */
public function testAdminAddPost() {
	$url = Router::url(array('admin' => true, 'controller' => 'users', 'action' => 'add'));
	$options = array(
		'method' => 'post',
		'return' => 'contents',
		'data' => array(
			'User' => array(
				'name' => 'test'
			)
		)
	);
	$result = $this->testAction($url, $options);
	$this->assertNull($result);

	$url = Router::url(array('admin' => true, 'controller' => 'users', 'action' => 'index'));
	$this->assertTextContains($url, $this->headers['Location']);
}

Note how I use dynamic URLs here to avoid routing changes affect all controller tests. So these tests effectively test the same URL as the frontend.

So basic tests should be made for

  • index (GET)
  • view (GET)
  • add (GET + POST)
  • edit (GET + POST)
  • delete (POST)

and their admin counterparts, if applicable.

Using controller tests also tests the views to the actions. Which is a nice side effect. Any warning/error popping up there will then also be visible right away.

For plugin controllers to be testable unfortunately you always need to use $uses, even if it wasn't necessary due to conventions. So for your Tools.TinyUrls Controller you would need

public $uses = array('Tools.TinyUrl');

Otherwise it would always try to look for the model/fixture in your app dir, which will eventually always fail.

Note: Do not forget to use --stderr when testing in CLI. Otherwise all tests that use the session (and which work fine in webtest runner) will fail:

cake test app AllController --stderr

When testing controllers that need authentication (like admin actions), you can either mock the Auth component or simply write to the session to log in a specific user/role in setUp() or before using testAction():

CakeSession::write('Auth.User', array(
	'username' => 'foo',
	'role_id' => $roleId,
	'id' => 1,
));

Don't forget to CakeSession::delete('Auth.User'); afterwards to avoid it affecting other tests. It is also a good practice then to use this to clear the session prior to any test using setUp().

Testing Shells

TODO

Testing Models

TODO

Testing Helpers

TODO

Test Coverage

If you want to generate a HTML overview of all your locale test coverage:

cake test app AllApp --stderr --log-junit tmp/coverage/unitreport.xml --coverage-html tmp/coverage --coverage-clover tmp/coverage/coverage.xml

The report index.html will be in your /tmp/coverage folder.

Clone this wiki locally