This weekend, some WordPress core devs ported the unit tests over to a new phpunit compatible runner. I was very excited about this, particularly because the tests I maintain define a constant (DOING_AJAX) which can impact other tests. Using process isolation should remove this impact, although at a performance cost. I used the @runTestsInSeparateProcesses annotation, but the tests failed. PHPUnit was restoring the global state (e.g. before the test split into a separate process) and it looked like this:
1.) Define all of the constants that were already defined
2.) Include the included files
This is the wrong process for the WordPress framework though. The included files were responsible for defining the constants. When they are included, they generate notices for defining constants that are already defined (by PHPUnit).
We all put our heads together and came up with a fix (props nacin) by hijacking PHPUnit_Framework_TestCase::prepareTemplate().
class MyTestCase extends PHPUnit_Framework_TestCase { /** * Define constants after requires/includes * @param Text_Template $template * @return void */ public function prepareTemplate( Text_Template $template ) { $template->setVar( array( 'constants' => '', 'zz_constants' => PHPUnit_Util_GlobalState::getConstantsAsString() )); parent::prepareTemplate( $template ); } }
Yes, this is hacky, and PHPUnit warns that prepareTemplate() was deprecated in 3.4.0. But when we looked, there were no other solutions, except disabling process isolation.
Alternate patch that uses reflection to rewrite the template: https://gist.github.com/ec35af03594246c6dd52
Another (much simpler) fix is to use the completely undocumented
@preserveGlobalState disabled
annotation in the test’s docblock.It’s not an equivalent fix, though. We did want the global state preserved between tests. However, the way phpunit was saving/restoring the state was problematic.
Ah, hadn’t thought of that! Good point.