Activating plugins in WordPress tests

Leveraging Codeception environments to activate and deactivate plugins in WordPress unit tests.

Environments

The Codeception test suite comes with environments support.
Quoting the Codeception site itself:

For cases where you need to run tests with different configurations you can define different config environments. The most typical use cases are running acceptance tests in different browsers, or running database tests using different database engines.

And while that’s very clear in possibility I recently came across some WordPress testing code that was going crazy ways to have a plugin active or inactive in a specific test case or method.
Functions like deactivate_plugins() or activate_plugins are required if trying to test the plugin or theme activation or deactivation routines; less so if the testing will behind a method or a whole case sounds like:

I want to make sure that my theme/plugin will do this when plugin A is active/inactive.

The easiest way to simulate such an “environment” is to use Codeception environment support itself; wp-browser will support it by extension.

An example

Say I’m developing a theme taking advantage of the “Posts to Posts” plugin.
During the setup the theme will check for the plugin existence and do something like offer an additional customizer controls, UI or meta boxes.
In my theme I’ve defined an Acme\Context class that’s in charge of abstracting the context the theme is operating into in a class.

namespace Acme;

class Context {
    public function p2p_is_active(){
        return defined('P2P_PLUGIN_VERSION');
    }
}

The class is simple enough (at this point!) and I want to test it and make sure the simple query method will return true or false as expected.
wp-browser is installed and configured and I’ve added a test in the wpunit test folder:

<?php

class EnvsTest extends \Codeception\TestCase\WPTestCase
{

    /**
     * @test
     * it should return false when p2p is not active (default)
     */
    public function it_should_return_false_when_p2p_is_not_active() {
        $context = new Acme\Context;
        $this->assertFalse($context->is_p2p_active());
    }

    /**
     * @test
     * it should return true when p2p is active
     * @env p2pon
     */
    public function it_should_return_true_when_p2p_is_active() {
        $context = new Acme\Context;
        $this->assertTrue($context->is_p2p_active());
    }

}

Note the @env annotation on the methods.
Configuring the wpunit.suite.yml file to support the two environments (default and p2pon) requires some additional lines:

# Codeception Test Suite Configuration

# suite for WordPress unit tests.
# Load WordPress and unit test classes that rely on it.
class_name: WpunitTester
modules:
    enabled: [WPLoader, \Helper\Wpunit]
    config:
        WPLoader:
            plugins: []
            activatePlugins: []
env:
    p2pon:
        modules:
            config:
                WPLoader:
                    plugins:
                        - posts-to-posts/posts-to-posts.php
                    activatePlugins:
                        - posts-to-posts/posts-to-posts.php

I’m now able to run the tests using the default environment (Posts to Posts not active) using:

codecept run wpunit

To run all of the test methods marked with the @env p2pon annotation I can use:

codecept run wpunit --env p2pon

No need for complex setups.