04. Dec. 2011

Unit-Testing Tips for 2.0 and PHPUnit

04 Dec

Quite some time ago I wrote about Unit testing. But that was still in 1.3 and with SimpleTest.
A lot has changed since then.

Execution Order

The documentation wasn’t all that clear about it. So I tried it with the following test file:

App::uses('MyCakeTestCase', 'Tools.Lib');
class TestCaseExecutionOrderTest extends MyCakeTestCase {
	public static function setUpBeforeClass() {
	public static function tearDownAfterClass() {
	public function setUp() {
	public function tearDown() {
	public function startTest() {
	public function endTest() {
	public function testFoo() {
		$this->out('* foo *');
	public function testBar() {
		$this->out('* bar *'); 

Note the parent calls for setUp and tearDown as well as setUpBeforeClass and tearDownAfterClass. Those need to be set. The other 2 methods don’t require this since they are not available in the parent class.
Also bear in mind that setUpBeforeClass and tearDownAfterClass need to be static. You cannot do dynamic stuff with it.

The result was pretty obvious:

* foo *
* bar *

Debug Output with PHPUnit >= 3.6

On the release notes of CakePHP2.0.3 you could find the note

A big difference people will notice when writing unit tests is that all output is swallowed by PHPUnit and not presented in either the web tester page nor in the CLI tester. To overcome this annoyance use the--debug modifier if you are using the CLI interface

Well, that broke a lot of existing debug code, of course.
So I tried to come up with a solution. The Shell uses a specific output(). Why not use sth like that in test cases, too?

 * outputs debug information during a web tester (browser) test case
 * since PHPUnit>=3.6 swallowes all output by default 
 * this is a convenience output handler since debug() or pr() have no effect
 * @param mixed $data
 * @param bool $pre should a pre tag be enclosed around the output
 * @return void
 * 2011-12-04 ms
public function out($data, $pre = true) {
	if ($pre) {
	} else {
		echo $data;
	if (empty($_SERVER['HTTP_HOST'])) {
		# cli mode / shell access: use the --debug modifier if you are using the CLI interface

As you probably noticed, I use it in the above "execution tryout".
You can make yourself a custom "MyCakeTestCase" class with then extends the core test case class and put it in there.

UPDATE January 2012

The core (>=2.0) now contains a native way to enable debugging output for your tests.
You need to append &debug=1 to the url. Not ideal, but it works*.

  • As long as your tests run through. On error the debug output will still be swallowed and you need to use the above snippet or append ob_flush() to all debug output manually.
5.00 avg. rating (94% score) - 1 vote

Posted by Mark in CakePHP, Testing


Tags: , ,

Leave a Reply

If you need to post a piece of code use {code type=php}...{/code}.
Allowed types are "php", "mysql", "html", "js", "css".

Please do not escape your post (leave all ", <, > and & as they are!). If you have encoded characters and need to reverse ("decode") it, you can do that here!

  1. flosky

    December 10, 2011 at 09:34

    Hi Marc,

    Thanks so much for this post. The first thing I thought when I upraded phpunit (and then cake) is: Where did all the nice output go?

    Most of my tests are still red, because I got the debug info (which is just what I wanted).

    Your solution works perfectly.
    You can also use debug(), which is what I’m doing now to get the previous behaviour back.


  2. Mark

    December 10, 2011 at 13:13

    Well, you can use anything besides debug(): pr() – echo – print_r – …
    They will all display their content on an error.
    But I was looking for a more persistent solution. Some of my Helper test cases for example output some result I want to see in the browser. Therefore I need to display the debug data even if everythings green 🙂
    My GoogleMapV3 helper displays the JS map which I can take a look at in the browser. I need to in order to validate if the JS works… So the output has to show in all cases.

    And this doesnt have to be visible in CLI mode. Therefore the switch.