We can all agree that WordPress has come a long way since its beginning and that it grew into something a lot 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 entry barrier for both content creators and developers. Sometimes this comes with 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 die-hard rules that prevent any backward compatibility breaking change when it comes to PHP code (Gutenberg is another story I won’t get into).
That legacy PHP code is often used by the developers that are starting to enter the world of programming, and the issue with that is they can learn some bad programming patterns. That in turn means they will reuse the poorly written code, increasing the amount of bad code in the world.
This is where WordPress gets its bad reputation in the developer community.
Breaking the cycle
So how can we break this cycle of bad code? By teaching new developers how they should write good code. One example of teaching new developers (but also old ones that are still clinging to the ‘WordPress’ way of doing things) is by writing tutorials.
Another way is to encourage them to use tools that can help them write better code.
I’m currently involved in the work which aims to release the new version of the WordPress Coding Standards, a set of rules used for the PHP_CodeSniffer tool that will let you know if your code has some potential issues (security, best practices, code style).
Another tool that I’ve recently developed is a package that will help developers set up WordPress integration tests that use the Pest testing framework.
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.
A lot of developers in the WordPress community go with the mantra: I can see that it works because I’ve tried it out in my browser. That’s OK, but there are issues with that.
First, it’s time-consuming. Every time you make some change, you need to make sure it works, but also that you didn’t break anything.
Second, people make mistakes. We are not foolproof, and code may be misused in ways you never thought possible. You would be amazed at how creative people can be when writing code.
Automated tests are quick and can help you in testing various cases that will happen when you execute your code.
You test for the intended behavior (happy path), and in a quick way, you can add examples of how your code can be used in a way you didn’t intend it to be used (unhappy path).
It also safeguards your code from regressions. A code regression is when you unintentionally break one part of your code by adding new code.
The problem with tests set up so far
Testing in WordPress is not a new thing. And it’s not like you couldn’t set up tests for your code before. There are amazing libraries out there that will help you set everything up like wp-browser.
But the problem is that the setup procedure is often clunky.
You need to set up a separate database for tests, and you need to run certain scripts, then change files to make it all work.
Let’s face it, it’s not a straightforward thing to do, and developers are by nature lazy creatures (that’s why we write code to do things for us 😄).
The aim of the wp-pest integration test setup is to eliminate all that extra work.
How to set it up
In order to set it up, your project must use Composer. It’s a de-facto standard way of adding packages to your code.
In your terminal type
composer require dingo-d/wp-pest-integration-test-setup --dev
After you’ve downloaded the package and its dependencies you can set up the theme tests by typing
vendor/bin/wp-pest setup theme
Or, in the case you want to set up 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 which WordPress version you’d like to test your code on.
In the background, a WordPress instance will be downloaded, and an in-memory database will be set up, along with two examples of tests that you can run.
Then, running either
vendor/bin/pest --group=unit
or
vendor/bin/pest --group=integration
will run the tests.
The beauty of Pest is that its syntax is developer-friendly. It has amazing documentation and great syntax. Let’s look at a simple example. Say you are registering 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 that 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');
});
Running 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 Tests\Integration\BooksCptTest
✓ Books custom post type is registered
Tests: 1 passed
Time: 0.14s
Conclusion
And just like that, you have the ability to run WordPress integration tests in your theme or plugin. Tests are amazing because not only are they safeguarding us from mistakes, but they also force us to write clean and testable code. This is especially true for plugins that have complicated logic or are communicating with third-party APIs.
Writing tests for such a codebase will force you to think about what your code architecture looks like so you can easily write automated tests – not to mention the time and money you’ll save from not having to manually test everything.
If you think this is something you might benefit from, feel free to use it, and star the repository on GitHub.
Hopefully, this will encourage more WordPress developers to use tools that will enhance their coding skills.