Disinstalling a WordPress plugin in Codeception

In a previous post I’ve presented a WordPress plugin requirement check baked into the wp-utils package and while that’s on the production side I want to be able to test the behaviours related to missing or incomplete requirements as well.
Codeception makes it easy using a cest format test and the fact that WordPress will consider a plugin “installed” when a .php file with a proper header is found in the plugins folder or in a first level sub-folder; that means that simply renaming a plugin main file removing the .php extension “uninstalls it” when it comes to WordPress logic.

The scenario

Plugin B requires Plugin A to work and I want to test that an helpful wp_die message is shown to the administrator when he tries to activate Plugin B while Plugin A is not installed.
Since that’s a test I need a reliable and programmatic way to “install” and “uninstall” a plugin on a per-test-method base without having to do any manual operations.

The code

I will use a cest test file format here to leverage the possibility offered by the _before and _after methods (PHPUnit equivalent of setUp and tearDown methods).


class ActivationAndInstallationRequirementsCest
    protected  $shouldRestorePluginAMainFile = false;
    protected $pluginAMainFile;

    public function _before()
        $this->pluginAMainFile = dirname(__FILE__) . '/../../../Plugin-A/plugin-A';

    public function _after()
        if(!file_exists($this->pluginAMainFile . '.php')){
            $this->shouldRestorePluginAMainFile = true;
            rename($this->pluginAMainFile, $this->pluginAMainFile. '.php');

    public function shouldShowWpDiePageIfPluginANotInstalled(AcceptanceTester $I)
        // setup

        // exercise

        // verify
        // make sure the wp_die page contains a link to install Plugin A

   protected function disinstallPluginAPlugin(){

       if(file_exists($this->pluginAMainFile . '.php')){
           $this->shouldRestorePluginAMainFile = rename($this->pluginAMainFile . '.php', $this->pluginAMainFile);


That’s all self explanatory and I could get rid of the _before method entirely hardcoding the path to the required plugin main file to slim down the test case further.