How to Start Testing Your WordPress Code with PHP Pest Testing Framework – WP Tavern

We can all agree that WordPress has come a long way from its beginnings and has become much more than blogging software.

At its core, it’s still a content management system (CMS), but with over 59,000 plugins in the wordpress.org directory, you can customize it to be much more.

The reason for its popularity is its low barrier to entry for content creators and developers. Sometimes it comes at a cost. It’s no secret that WordPress has a bad reputation when it comes to development. It has a lot of legacy baggage and hard and fast rules that prevent any backward compatibility breaking changes when it comes to PHP code (Gutenberg is another story that I won’t go into).

This legacy PHP code is often used by developers who are starting to enter the world of programming, and the problem is that they can learn bad programming patterns. This in turn means that they will reuse badly written code, increasing the amount of bad code in the world.

This is where WordPress gets its bad reputation in the developer community.

Break the cycle

So how can we break this cycle of bad code? By teaching new developers how to write good code. An example of teaching new developers (but also old ones still clinging to the “WordPress” way of doing things) is to write tutorials.

Another way is to encourage them to use tools that can help them write better code.

I am currently involved in the work that aims to release the new version of the WordPress Coding Standardsa set of rules used for PHP_CodeSniffer tool that will let you know if your code has potential problems (security, best practices, code style).

Another tool that I recently developed is a wrap which will help developers set up WordPress integration tests that use the pest testing frame.

Ok, so why do we need this new tool?

The main motivation behind creating this package is to encourage more people to write tests for their code, especially plugin developers.

Many developers in the WordPress community follow the mantra: I can see it working because I’ve tried it in my browser. It’s OK, but there are problems with it.

First of all, it takes time. Every time you make a change, you need to make sure it works, but also that you haven’t broken anything.

Second, people make mistakes. We are not infallible and code can be misused in ways you never thought possible. You’d be amazed at how creative people can be when writing code.

Automated tests are fast and can help you test various cases that will occur when you run your code.

You test the intended behavior (happy path), and in a quick way you can add examples of how your code can be used in ways you didn’t intend to use (unlucky path).

It also protects your code from regressions. A code regression occurs when you unintentionally break some of your code by adding new code.

The problem with the tests implemented so far

Testing in WordPress is nothing new. And it’s not like you couldn’t set up tests for your code before. There are amazing libraries that will help you to configure everything like wp browser.

But the problem is that the setup procedure is often clunky.

You need to set up a separate database for testing and you need to run some scripts and then modify the files to make everything work.

Let’s face it, it’s not a simple thing to do, and developers are inherently lazy creatures (that’s why we write code to do things for us 😄).

The goal of setting up the wp-pest integration test is to eliminate all that extra work.

How to set it up

To set it up, your project must use Composer. It’s a de facto standard way to add packages to your code.

In your terminal type

composer require dingo-d/wp-pest-integration-test-setup --dev

After downloading the package and its dependencies, you can configure theme testing by typing

vendor/bin/wp-pest setup theme

Or, in case you want to set up some tests for your plugin, you can write

vendor/bin/wp-pest setup plugin --plugin-slug=your-plugin-slug

Optionally, you can provide a --wp-version parameter, to specify the version of WordPress on which you want to test your code.

In the background, a WordPress instance will be downloaded and an in-memory database will be configured, along with two sample tests you can run.

Then, running either

vendor/bin/pest --group=unit

or

vendor/bin/pest --group=integration

will perform the tests.

The beauty of Pest is that its syntax is developer-friendly. He has amazing documentation and excellent syntax. Let’s take a simple example. Let’s say you register a custom post type called “Books”:

 esc_html__( 'Books', 'test-plugin' ),
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'query_var'          => true,
        'rewrite'            => array( 'slug' => 'book' ),
        'capability_type'    => 'post',
        'has_archive'        => true,
        'hierarchical'       => false,
        'menu_position'      => null,
        'supports'           => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ),
    );
 
    register_post_type( 'book', $args );
}
 
add_action( 'init', 'test_plugin_register_books_cpt' );

After running the setup command which adds an example, a test called BooksCptTest.php would look like this:

assertNotFalse(has_action('init', 'test_plugin_register_books_cpt'));

	$registeredPostTypes = get_post_types();

	// Or we can use expectations API from Pest.
	expect($registeredPostTypes)
		->toBeArray()
		->toHaveKey('book');
});

Working vendor/bin/pest --group=integration gives us the following output:

Installing...
Running as single site... To run multisite, use -c tests/phpunit/multisite.xml
Not running ajax tests. To execute these, use --group ajax.
Not running ms-files tests. To execute these, use --group ms-files.
Not running external-http tests. To execute these, use --group external-http.

   PASS  TestsIntegrationBooksCptTest
  ✓ Books custom post type is registered

  Tests:  1 passed
  Time:   0.14s

Conclusion

And just like that, you have the option to run WordPress integration tests in your theme or plugin. Testing is amazing because not only does it protect us from errors, but it also forces us to write clean, testable code. This is especially true for plugins that have complicated logic or communicate with third-party APIs.

Writing tests for such a code base will force you to think about how your code architecture will look so that you can easily write automated tests – not to mention the time and money you’ll save by not having not to test everything manually.

If you think this is something you could benefit from, feel free to use it, and start repository on GitHub.

Hopefully this will encourage more WordPress developers to use tools that will improve their coding skills.

Esther L. Gunn