In this article I’m going to show you how to do unit testing in Wordpress plugins. Previously I’ve written an article on Getting Started with Wordpress Plugin Development and in that article I’ve created a simple Wordpress plugin that saves some tweets in the Wordpress database and displays them on a widget. This time I’m going to walk you through setting up unit testing in Wordpress then write some tests for that specific plugin. If you want to follow along you can download the source from here.
First you have to install composer. From your terminal execute the following command to install composer:
Next on your project directory. In my case its in:
composer.json file then put the following contents:
1 2 3 4 5
Once you’re done, save the file then execute the following command from your terminal:
This will install PHPUnit which we will be using for unit testing.
Setting Up Wordpress Tests
Another prerequisite before we can start writing our unit tests is installing Wordpress Tests which is a tool that was created to help in unit testing Wordpress plugins. The main benefit of using this tool is that it has access to all the Wordpress classes so the unit testing environment is pretty much the same as the environment where your Wordpress plugins runs.
Next create a
src folder from the root directory of your plugin.
Then install Wordpress Tests inside of it. You can install by cloning the repo by executing the following command from the terminal:
Or simply download the
master.zip file from the master branch of the project if you don’t have Git installed.
Next create a
tests directory (still on the root directory of your plugin). Then inside it create another directory and name it the same name where your Wordpress plugin is stored. In this case I’ve named it
zam since its the name of the directory where the main plugin file is located.
Then create a
bootstrap.php file just beside the directory that you’ve just created and put the following contents:
1 2 3 4 5 6 7 8 9 10
Ok not exactly the same contents but at least the same format. All you’re going to need to have to change here is the value for the
$path. It should be where the main
bootstrap.php file is stored. Not the
bootstrap.php that you’ve just created but the
bootstrap.php file that’s inside the
wordpress-tests project which you cloned earlier.
Next inside the
tests/zam directory create the file were we are going to write all the tests later on. As a convention the naming should be the name of the plugin followed by the word
Test. So for the sample plugin that were going to test the name would be
Next navigate to the root directory of your plugin and create a
phpunit.xml file and put the following contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
phpunit.xml file simply points out where the test directory is located and some options for PHPUnit.
phpunit.xml file above we’ve used the following options:
- backupGlobals – setting this to
falsetells PHPUnit to disable global state between tests
- backupStaticAttributes – setting this to
falsedisables the backup and restore operations for static class attributes
- colors – setting this to
trueenables syntax highlighting when running tests on the terminal
- convertErrorsToExceptions – setting this to
trueconverts errors to exceptions
- convertNoticesToExceptions – setting this to
trueconverts notices to exceptions
- convertWarningsToExceptions – setting this to
trueconverts warnings to exceptions
- processIsolation – setting this to
falsedisables running each test in a separate PHP process
- stopOnFailure – setting this to
falsedisables stopping of execution upon first error or failure. This means that the test will continue to run even after encountering a failure
- syntaxCheck – setting this to
falsedisables checking of syntax
- bootstrap – where the
bootstrap.phpfile is located
Setting Up the Test Database
If your plugin uses the Wordpress database then its a requirement that you also have to setup the testing database so that running the tests won’t affect your actual database.
To do that go ahead and backup your Wordpress database using a tool like Phpmyadmin.
Then restore the backup this time giving it a different name, something like
wp_db_tests to indicate that its a database that will be used for testing.
wp-config.php to make use of the test database temporarily.
1 2 3
After that you can install the Wordpress reset plugin to reset the database that will be used for testing.
Once the test database has been successfully reset you can now revert the changes to
wp-config.php and use your old database:
1 2 3
Unit Test Configuration
Next we can now specify the options to the unit test configuration file (
unittests-config.php) which you can find inside the
The only things that you might want to change here are the values for
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
Examining the Testing Suite
Now were ready to write some unit tests. Go ahead and navigate to the following directory:
Open up the
zamTest.php file and put the following contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
The unit testing class will simply extend the
WP_UnitTestCase class which is inside the
Let’s take a moment to inspect it before proceeding with writing our tests.
As you can see the
WP_UnitTestCase class is simply extending the
PHPUnit_Framework_TestCase which is the main testing suite that is used for most PHPUnit based test classes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
setUp method sets the
supress_errors attribute of the
$wpdb object to
false this means that all database errors will be displayed if there are any. The
$wpdb variable is an instance of the Wordpress database class. It’s also setting the
show_errors attribute to
true. Then it connects to the database that we have set on the
unittests-config.php file earlier using the
db_connect() method. It also sets
1 which basically means that all errors, warnings and notices will be displayed if there are any.
clean_up_global_scope() method is called, this simply empties out global variables such as
$_POST. This method also calls up another method which is the
flush_cache() which simply resets the Wordpress object cache. All of this is done to prevent any external variable or cached data from interfering with the values used for the current test. The
setUp method also calls up the
start_transaction() method which sets database
0. This means that even if you execute a query like:
It won’t actually commit the changes to the database. This means that the changes aren’t permanently added into the database. After that it also starts a transaction using the
START_TRANSACTION command. What this does is to ensure that the
autocommit remains disabled while the transaction hasn’t been ended yet. You can only end a transaction using either the
ROLLBACK command. The
COMMIT command simply commits all the changes in the database. The
ROLLBACK command rolls back everything that was done after the
When you check out the
tearDown() method you will see that the
WP_UnitTestCase class uses the
ROLLBACK command. This means that every change brought by each test is rolled back to its previous state.
So even if a test method does a couple of queries:
1 2 3 4
Once the the execution of the test method ends, the
tearDown() method will be called and the database will be rolled back to its previous state before any of the queries above were executed.
This effectively brings back the test database to a state similar to that of when your first installed Wordpress on every test.
There’s also the
assertWPError() method which simply asserts a Wordpress error if its
assertEqualFields() method simply checks if each key-value pair that you supply it has equal values. If not the test will fail.
assertDiscardWhitespace() method simply removes all the whitespace from 2 strings and compare it with each other.
checkAtLeastPHPVersion() method checks if the PHP Version number that you specify as its argument is higher than that of PHP Version in the machine where you are running the tests.
Lastly there’s the
go_to() method which sets up the objects which you might want to check when navigating a specific URL. For example if you want to assert the title of a specific page you do something like:
Then you simply use an instance of the
$wp_query class to get the queried objects from that specific URL.
This will then contain some attributes like the
post_content which you can assert:
1 2 3 4 5 6 7 8
Writing Unit Tests
Now that we know what the
WP_UnitTestCase class does we can now proceed with writing the actual tests for our simple plugin.
setUp method is where we setup the things that the plugin needs during its runtime. For example if the plugin that you are testing involves creating database tables or adding new entries to the
wp_options table then you set those all up in the
setUp method. Think of it as emulating what would usually happen once the plugin is activated on a Wordpress site. The same thing should happen in the
The first thing that we need to do inside the
setUp method is call the
setUp method in the
WP_UnitTestCase class. This simply cleans up the global scope and start a database transaction as we discussed earlier.
Next we create a new object for the
Zam plugin class and call its
installation_housekeeping() method which creates the tables that will be needed by the plugin. Finally, we set the option that will be used by the plugin.
Here were setting the
zam_twitter_id under the
zam_options option group to be equal to
Wern_Ancheta. This should be a valid twitter username otherwise it wouldn’t work.
1 2 3 4 5 6 7 8 9 10 11 12
Remember that the `setUp` method runs before every test is executed.
Next is the
tearDown() method. This is the opposite of the
setUp method in that it is run after every test has been executed. What it does is to simply clean up the things which aren’t cleaned up by the
setUp method. In this case were simply calling the
uninstall_housekeeping() method which drops the tables that are used by the plugin.
1 2 3 4 5 6 7
Now were ready to test the actual methods in the plugin. For this tutorial were only going to test 2 core methods which the plugin uses, the
The convention that I’ve used in the following methods is to prefix the actual name of the methods that I’m testing with the word
test_. Of course you can use other conventions but remember to use one that’s already followed by your plugin. For example here I’ve used underscores to separate each word in the method. You can also use camel casing or hungarian notation if you’re already using it. What’s important is that the test should follow the convention used by the actual class that you’re testing.
Get Tweets Test
To test the
get_tweets() method first you have to instantiate the plugin.
This should be true for every method to avoid storing of values in the class itself.
Once you’ve instantiated the class, call the
get_tweets() method using the object that you’ve used.
We expect the
get_tweets() method to return 11 tweets by default so we use
assertCount to assert that the number of items stored in the
$tweets variable is indeed 11.
1 2 3 4 5 6 7 8 9
Save Tweets Test
Finally we test the
save_tweet method. This method saves a random tweet from a page specified by the user in a specific Wordpress post.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
This method is using the Shortcode API which has a general syntax similar to this one:
zam_tweets is the specific shortcode ID used by the plugin. And
page is the attribute and
3 is the value for that attribute.
What were doing here is simply emulating what would actually happen in an actual scenario. First the user creates a new post, puts in the shortcode then publish the post. But when testing we can take shortcuts as we don’t need to navigate to the post page and click on the add new post. All that we need to do is to publish the actual post and that is done by calling the
wp_insert_post() method. This takes a couple of arguments but here were only specify the
post_title or the actual title of the post, the
post_content or the shortcode itself, and the
post_type which is
Then we get the tweet from the tweets table, call the
get_tweets() method, this time specifying the same page that was used in the shortcode. Finally we simply assert that the
in_array() method which checks if the tweet that was found in the database is in the array of tweets returned by the
get_tweets() method is
Running the Tests
Once you’re done writing the tests you can simply open up the terminal on the root directory of the plugin and execute the following command:
Once its done running you will see a screen similar to this: