1

I'm using phpunit to do TDD on a WordPress plugin. One of the requirements is that plugin activation fail if a taxonomy with a predefined name, let's say "apartments", is already registered (either by the theme or another plugin).

The problem is, using the standard WordPress phpunit testing suite, the plugin is activated as a "mu-plugin" automatically while the WordPress environment is bootstrapped. This post suggesting manually activating the plugin but we've tried that and it doesn't seem to work (WordPress 5.2.1). In fact, there is zero indication the function in that post does anything. I have a feeling it is because the plugin activation code probably won't run if a plugin is mu or already activated.

Before going through the code trying to figure out what's happening, I'm wondering:

  1. Is this even a proper use of phpunit in the context of WordPress plugins?
  2. If it is a proper use, how should I go about setting up such a test (checking if plugin activation fails)?

Help is greatly appreciated.

2 Answers 2

2
  1. Testing of WP plugins and themes with phpunit is absolutely proper and widely used. You can see an example of pure phpunit tests in our plugin Cyr2Lat (please look at test folder).

What you can find there, it is an example of pure phpunit tests, which work with testing class only and mock everything other.

Tests based on WP_UnitTestCase we call "integration tests", as they load the whole WordPress core and work with database.

  1. You can make testing of plugin activation by both approaches mentioned above. With pure phpunit tests, you can just check behavior of your class responsible for activation.

If you prefer to use WP_UnitTestCase, you should modify bootstrap.php to prevent direct loading of the plugin, hook to 'taxonomy_registered' for post, register your own taxonomy, do action 'activate' for your plugin, and check if it became activated. This is how I see the sequence.

1
  • The link to the sample tests is very helpful, thanks. I was really hoping for a way to use the WP_UnitTestCase without having to modify bootstrap.php to keep the tests portable but I understand the issue. Thanks! Commented Jun 20, 2019 at 21:17
1

There are a few things to consider:

First of all, WHAT are you testing? You shouldn't need to test the normal activation / deactivation process of WordPress itself. You should be testing the effects of your particular plugin. What are they? [The most common thing we're testing for here is data removal and setup.]

When you activate a plugin in WordPress, numerous things happen, including THREE separate page requests. The initial state where the plugin is not activated, there is an invisible "hop" request that happens in the background which is where most activation stuff happens, and a final resting state request where the plugin is fully activated.

If you want to test the entire process, consider a Selenium / browser test using something like WP-Codeception. In these tests, you have a browser that actually goes and manually clicks on an active WordPress install.

Or you could use WP-CLI to activate the plugin and test whatever artifacts you expect to happen. Again use WordPress Codeception [which is a wrapper of PHPUnit].

Or finally you can to a unit test on the function that is being called during activation using PHPUnit. i.e.:

<?php

class DeactivationTest
{

    /**
     * @test
     * it should remove data
     */
    public function isShouldRemoveData(){
        //Given there is some data that should be removed upon deactivation
        $data = setupYourMockDataFunc();
        
        //When the deactivation function is called
        yourDeactivationFunc($data);
        
        //Then the data should be removed
        $this->assertEmpty($data);
    }
}

A Codeception / Selenium style acceptance test:

class ActivatePluginCest
{
    public function activateThePlugin(\AcceptanceTester $I){
        $I->wantTo('Activate the plugin');
        $I->loginAsAdmin();
        $I->see("Howdy, Admin");
        $I->wantTo("deactivate the plugin first");
        shell_exec("wp plugin deactivate my-plugin");
        $I->wantTo('Activate the plugin');
        $I->expect('to be able to click the activation link.');
        $I->amOnPage("/wp-admin/plugins.php");
        $I->click("#activate-my-plugin");
        $I->amOnPage("/wp-admin/tools.php?page=my-plugin");
        $I->see("My Plugin");
    }
}
2
  • Thanks John. To be clear, I'm running some code (just a few lines) on activation of the plugin. I'm trying to make sure the lines succeed and don't cause the plugin to fail to activate. Now that I've written this, I see what you mean about WHAT am I testing. Activation probably shouldn't be the measure by which I determine whether or not the code succeeds or fails. I'll review. Thanks! Commented Mar 25, 2022 at 13:17
  • That's still something that is often important to test. I updated my answer to include a browser test that activates a plugin.
    – John Dee
    Commented Mar 26, 2022 at 0:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.