Unit testing PHP code in WordPress is not a straightforward task. Automated tests in WordPress use PHPUnit as a base. But there is lots of additional code added on top to adapt the framework to work with WordPress.

In this article we’ll look at the most common unit test issues in WordPress. For each issue, we’ll try and provide a fix, or a workaround.


If you are interested in learning more about unit testing in WordPress, I recommend having a look at my WordPress Unit Testing Explained course.


Test Runner

Why does the test runner “hang” for a long time before running the first test?

When the WP_UnitTestCase::setUp() method is first called for a test case, it will create a list of all files in the uploads directory of the test install. The more files there are in this directory, the longer this takes. See Trac ticket #50209 for background information.

To work around this, use the upload_dir filter to use a different uploads directory for tests. You can place this code snippet in your test’s bootstrap.php file to achieve this:

tests_add_filter( 'upload_dir', function( $dir ) { array_walk( $dir, function( &$item ) { if ( is_string( $item ) ) { $item = str_replace( '/uploads', '/test-uploads', $item ); } } ); return $dir; } );

Fixtures

For general information on how fixture creation and deletion works in the WordPress unit testing framework, I recommend reading Understanding WordPress PHP Unit Test Fixture Setup and Teardown.

I added a callback function to a hook (using add_action or add_filter) in a test, but it’s not working in another test, why?

Hooks are reset between every test method. There are two approaches to workaround this:

  1. Use the setUp() method add the action or filter callback before every test run. In this case you do not need to remove this hook callback. The WordPress testing framework will reset any changes to filters and actions after each test method.
  2. Use the wpSetupBeforeClass() method to add the action or filter callback before the first test run. This will prevent this change to the filters and actions from being reset after each test run. You need to remove this hook callback in the wpTeardownAfterClass() to ensure the test case leaves a clean slate for the next test.

I created a fixture in a test, but cannot access it in another test, why?

The database, and with that any fixtures created in a test method, are deleted between every test.

If you want to share database fixtures between tests, you need to create them inside of the wpSetupBeforeClass() method of your test case.

Factories (WP_UnitTest_Factory class)

For general information on how to interact with the factories in the WordPress unit testing framework, I recommend reading WP_UnitTest_Factory: The Missing Documentation.

Why can’t I set the post_modified and post_modified_gmt properties of WP_Post fixture?

When using the Factory’s create methods for creating a post, then you cannot set the post_modified and post_modified_gmt properties of the fixture.

Instead you need to first create the post fixture, and then use the ::update_post_modified() method to set these fields.

function test_sample() { $post_id = self::factory()->post->create( array( 'post_date' => '2012-03-05 15:30:55', ) ); $this->update_post_modified( $post_id, '2014-11-03 14:43:00' ); }

Do you have another issue that is not on this page?

Feel free to reach out with a precise issue description. I’ll update this article with a solution of workaround as soon as possible.