WordPress Plugin Acceptance Test with Codeception on VVV

Ever anxious about pushing new release of WordPress plugin causing the white screen of death on your clients’ sites? You should write some acceptance tests! I will demonstrate how to leverage Varying Vagrant Vagrants, Codeception and wp-browser to write acceptance tests for WordPress plugins.

The Tools

Codeception

Codeception is a PHP testing framework built on PHPUnit that automates acceptance testing. It does functional and unit tests also.

wp-browser

wp-browser is a WordPress specific set of extensions for Codeception written by theAverageDev.

The package includes a class extending Codeception PhpBrowser module that adds WordPress related assertions for cest and cept tests, an extension of Codeception own Db module meant to allow for more comfortable WordPress specific database handling and testing and a class taking care of installing and loading a WordPress installation relying on WordPress automated testing suite.

Start with VVV

We’ll run our tests from within VVV because WP CLI, Node, and Composer are already installed for us there.

Before we actually writing the tests, we need a WordPress installation and a plugin to test. I use my plugin Remove Medium Cross Links as an example. All it does is remove the medium cross link footer from WordPress post.

Medium Cross Link Footer

Medium Cross Link Footer

Preparation

Create a WordPress site in VVV so that we can run our plugin on.

$ vv create
New VVV Site Setup
Name of new site directory: rmcl-tester

And create our plugin.

$ vagrant ssh
$ cd /srv/www/rmcl-test/htdocs/wp-content/plugins
$ wp scaffold plugin remove-medium-cross-links

The plugin is simple. Add these lines in remove-medium-cross-links.php

function remove_medium_cross_links() {
	remove_action( 'init', array( 'Medium_Site', 'init' ) );
}

if ( ! is_admin() ) {
	add_action( 'init', 'remove_medium_cross_links', 5 );
}

Test Manually

  1. Head to rmcl-tester.dev
  2. Install and activate the official Medium plugin
  3. Add the Medium Integration Token on your profile page
  4. Add a new post and make sure it cross posted to medium
  5. Go to the new post. You should see the cross link footer
  6. Activate our remove-medium-cross-links plugin
  7. Go back the post. The cross link footer should be gone

Database Snapshot

Codeception will reset the database between every test. We need to make this database dump.

$ wp db export tests/_data/dump.sql --path=/srv/www/rmcl-test/htdocs
Success: Exported to 'tests/_data/dump.sql'.

If you have a more complex setup, you could use WP Migrate DB Pro to fine tune the sql dump.

Start Testing

Install latest stable WPBrowser package via Composer:

$ composer require lucatume/wp-browser --dev

It might take a while. But once it’s done, we can configure Codeception and wp-browser. Answer the questions. Use default if not shown below.

$ vendor/bin/wpcept bootstrap -i
MySQL database host? (localhost) rmcl-test.dev
Test database name? (database) rmcl-test
Test database password? () root
Integration tests database password? () root
WordPress site url? (http://wp.dev) http://rmcl-test.dev
Absolute path to the WordPress root directory? (/var/www/wp) /srv/www/rmcl-test/htdocs/
Activate a plugin? (order matters, leave blank to move on) medium/medium.php
Activate a plugin? (order matters, leave blank to move on) remove-medium-cross-links/remove-medium-cross-links.php

Acceptance Test for Real

Time for our first acceptance test.

$ vendor/bin/wpcept generate:cept acceptance RemoveMediumCrossLinkFooter

In the generated tests/acceptance/RemoveMediumCrossLinkFooterCept.php

<?php 
$I = new AcceptanceTester($scenario); $I->wantTo('test medium cross link footer is removed');

$I->amOnpage('/');
$I->click('Acceptance Test for rmcl');

$I->dontSee('Also published on Medium.');

However, it’s dangerous to just testing what we don’t see. Make a sanity check also.

$ vendor/bin/wpcept generate:cept acceptance SanityCheck

In tests/acceptance/SanityCheckCept.php:

<?php 
$I = new AcceptanceTester($scenario); $I->wantTo('see medium cross link footer when rmcl is deactivated');

$I->loginAsAdmin();
$I->amOnPluginsPage();
$I->deactivatePlugin('remove-medium-cross-links');

$I->amOnpage('/');
$I->click('Acceptance Test for rmcl');

$I->see('Also published on Medium.');

Note: loginAsAdmin(), amOnPluginsPage() and deactivatePlugin come from wp-browser. Check the docs for more WordPress-specific methods.

Run the Acceptance Tests

$ vendor/bin/wpcept run acceptance

If you follow along, your tests should pass.

wpcept run acceptance

wpcept run acceptance

Real Browser Testing

Two green ticks sounds good. But where is the freaky browser jumping around and clicking itself you found on all those acceptance test demo? By default wp-browser run acceptance tests on WPBrowser, a PHP based, JavaScript-less and headless browser for acceptance testing not requiring JavaScript support.

We can do better, since VVV doesn’t provide GUI support. We will run the tests outside VVV, using your real browsers.

Selenium Server

Open a new tab in the terminal:

$ npm install selenium-standalone@latest -g
$ selenium-standalone install
$ selenium-standalone start

Note: The default version coms with this package is quite old. You can use $ selenium-standalone install --version=3.0.1 --drivers.firefox.version=0.13.0 --drivers.chrome.version=2.27 and $ selenium-standalone start --version=3.0.1 --drivers.firefox.version=0.13.0 --drivers.chrome.version=2.27 to specific selenium and drivers versions.

WPWebDriver

WPWebDriver – a Guzzle based, JavaScript capable web driver; to be used in conjunction with a Selenium server, PhantomJS or any real web browser for acceptance testing requiring JavaScript support

Head back to tests/acceptance.suite.yml and instruct Codeception to use WPWebDriver instead.

class_name: AcceptanceTester
modules:
    enabled:
        - \Helper\Acceptance
        - WPDb
        - WPWebDriver
    config:
        WPDb:
            dsn: 'mysql:host=rmcl-test.dev;dbname=rmcl-test'
            user: root
            password: root
            dump: tests/_data/dump.sql
            populate: true
            cleanup: true
            url: 'http://rmcl-test.dev'
            tablePrefix: wp_
        WPWebDriver:
            url: 'http://rmcl-test.dev'
            adminUsername: admin
            adminPassword: password
            adminPath: /wp-admin
            wait: 5
            host: '192.168.50.1'
            browser: chrome

Run the Acceptance Tests Again

With $ selenium-standalone start running in another tab.

$ vendor/bin/wpcept build
$ vendor/bin/wpcept run acceptance

Always good idea to run $ wpcept build whenever you changed the config files.

A chrome tab will jump out and freaking around this time. As before, the tests should pass.

Stay tuned

Be sure to subscribe the my newsletter. I will talk about how to run these acceptance tests on TravisCI soon.