When unit testing a plugin, does the plugin need to be in the wp-content/plugins directory of the WordPress tests install?

TL;DR

It can be anywhere on the filesystem.

(But see the update below for a tool that will help you do this even more realistically.)

Explanation

The plugin can be anywhere on the filesystem, depending on whether your plugin has an install function and how you want to run that.

If your plugin creates database tables or saves default options in the database on activation, then just loading your plugin like that won’t cause your plugin to be installed, and so your plugin probably won’t work properly. So in addition to loading the plugin you also need to install it.

The way that WordPress does this is using the activate_plugin() function, which will call the plugin’s activation hook that was registered with register_activation_hook().

However, activate_plugin() validates that the plugin exists in the wp-content/plugins folder, so if you install the plugin that way you’ll have to actually have your plugin (or a symlink to it) in the plugins directory.

This is a pain, so I usually do not use activate_plugin() to install the plugin. Instead I call whatever function you’ve registered with register_activation_hook() directly. This may not be ideal, but I haven’t experienced any unintended side-effects from it.

So you’d have something like this:

tests_add_filter( 'muplugins_loaded', function() {
    require '/path/to/plugin/anywhere/on/filesystem/myplugin/myplugin.php'

    my_plugin_install_function();
} );

Of course, if your plugin doesn’t have an install function, this point is moot, and you probably don’t have to worry about activating/installing the plugin at all. Just load it from anywhere on the filesystem and your tests should work fine.

WebDriver Tests

Note that there may (probably should) come a time when you want to run acceptance tests for your plugin. Depending on how you decide to do this, you would need to have your plugin actually activated on the site the WebDriver browser is visiting.

WP Browser offers several options for doing this with PHPUnit via Codeception. None of the options that it currently offers actually load the plugin on the tests side in addition to the client/remote side, so the site being used in the WebDriver tests is completely decoupled from the one used in the unit tests. (However, I am currently working on a hybrid approach that does use the same site and load on the tests side while running the WebDriver tests.)

Update Nov 2016

Although everything I said above is still true, and loading the plugin this way hasn’t caused any problems to speak of, I have recently decided to pursue greater realism in how the plugin is loaded and installed during the unit tests. To this end, I’ve created a little library called WPPPB, or the WordPress Plugin PHPUnit Bootstrap. When using it, loading your plugin is as simple as this:

$loader = WPPPB_Loader::instance();
$loader->add_plugin( 'my-plugin/my-plugin.php' );
$loader->load_wordpress();

This is deceptively simple, as behind the scenes the plugin is activated remotely, before WordPress is loaded, so that it can then be loaded by WordPress exactly as it normally would “in real life”. This does require you to have a symlink to the plugin in the plugins folder, but the library includes a script that will set everything up for you automatically. (Pro tip: WPPPB also includes tools to help you test plugin un/installation very realistically as well.)

Leave a Comment