Testing with PHPUnit 7 for WordPress

Last Revised: October 2, 2021

One of the ways to collaborate on WordPress code is to verify that the PHP code is normalized and working properly. For this, the WordPress core development team has decided to test phpUnit.

The examples and code presented here are based on installing and configuring VPS with Subversion. From this configuration we will review the system with PHPUnit.

Installing PHPUnit

The first thing we will do is install and configure PHPUnit globally. To do this we just have to follow the following steps.

cd
wget -O phpunit https://phar.phpunit.de/phpunit-7.phar
chmod +x phpunit
mv phpunit /usr/local/bin/phpunit
phpunit --version

This last command will show us the current version of the software so that we will know that it is working.

Test database

These tests remove all the contents of the database, so before we continue, we will create a parallel database in which the tests will be performed. We will use the same model as in the creation of the main database.

mysql -u root -p

You will need a password for this exclusive database for our WordPress test. Please create your own password that is somewhat secure.

CREATE DATABASE wordpresstest CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin;
GRANT ALL ON wordpresstest.* TO 'wordpresstest'@'localhost' IDENTIFIED BY '__PASSWORD__';
GRANT ALL ON wordpresstest.* TO 'wordpresstest'@'127.0.0.1' IDENTIFIED BY '__PASSWORD__';
FLUSH PRIVILEGES;
quit

Setting up WordPress for testing

Now that we have the software installed and a test database, we will create a configuration file in which to incorporate this information.

cd /webs/wordpress-svn/
vim wp-tests-config.php

The file will incorporate a configuration like this. NOTE: Check the connection data and other elements throughout the file.

<?php

/* Path to the WordPress codebase you'd like to test. Add a forward slash in the end. */
if ( defined( 'WP_RUN_CORE_TESTS' ) && WP_RUN_CORE_TESTS ) {
  define( 'ABSPATH', dirname( __FILE__ ) . '/build/' );
} else {
  define( 'ABSPATH', dirname( __FILE__ ) . '/src/' );
}

/*
 * Path to the theme to test with.
 *
 * The 'default' theme is symlinked from test/phpunit/data/themedir1/default into
 * the themes directory of the WordPress installation defined above.
 */
define( 'WP_DEFAULT_THEME', 'default' );

// Test with multisite enabled.
// Alternatively, use the tests/phpunit/multisite.xml configuration file.
// define( 'WP_TESTS_MULTISITE', true );

// Force known bugs to be run.
// Tests with an associated Trac ticket that is still open are normally skipped.
// define( 'WP_TESTS_FORCE_KNOWN_BUGS', true );

// Test with WordPress debug mode (default).
define( 'WP_DEBUG', true );

// ** MySQL settings ** //

// This configuration file will be used by the copy of WordPress being tested.
// wordpress/wp-config.php will be ignored.

// WARNING WARNING WARNING!
// These tests will DROP ALL TABLES in the database with the prefix named below.
// DO NOT use a production database or one that is shared with something else.

define( 'DB_NAME', 'wordpresstest' );
define( 'DB_USER', 'wordpresstest' );
define( 'DB_PASSWORD', '__PASSWORD__' );
define( 'DB_HOST', 'localhost' );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', 'utf8mb4_bin' );

/**#@+
 * Authentication Unique Keys and Salts.
 *
 * Change these to different unique phrases!
 * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}
 */
define( 'AUTH_KEY',         'put your unique phrase here' );
define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
define( 'LOGGED_IN_KEY',    'put your unique phrase here' );
define( 'NONCE_KEY',        'put your unique phrase here' );
define( 'AUTH_SALT',        'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT',   'put your unique phrase here' );
define( 'NONCE_SALT',       'put your unique phrase here' );

$table_prefix = 'wptests_';   // Only numbers, letters, and underscores please!

define( 'WP_TESTS_DOMAIN', 'example.com' );
define( 'WP_TESTS_EMAIL', 'hello@example.com' );
define( 'WP_TESTS_TITLE', 'Test Blog' );

define( 'WP_PHP_BINARY', 'php' );

Start of the test with PHPUnit

The next thing we’ll do is prepare a WordPress setup ready for testing. Therefore, we will launch a series of commands to prepare the system. The last of the commands will run the PHPUnit test.

cd /webs/wordpress-svn/
npm update
npm run grunt build
npm run grunt watch
phpunit

This should return something such that:

user@wordpress-svn:/webs/wordpress-svn# phpunit
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.
PHPUnit 7.5.18 by Sebastian Bergmann and contributors.
…………………………………………………..    59 / 10082 (  0%)
…
…………………………………………………..  9086 / 10082 ( 90%)
…………………………………………………..  9145 / 10082 ( 90%)
…………………………………………………..  9204 / 10082 ( 91%)
…………………………………………………..  9263 / 10082 ( 91%)
…………………………………………………..  9322 / 10082 ( 92%)
…………………………………………………..  9381 / 10082 ( 93%)
…………………………………………………..  9440 / 10082 ( 93%)
…………………………………………………..  9499 / 10082 ( 94%)
…………………………………………………..  9558 / 10082 ( 94%)
…………………………………………………..  9617 / 10082 ( 95%)
…………………………………………………..  9676 / 10082 ( 95%)
…………………………………………………..  9735 / 10082 ( 96%)
…………………………………………………..  9794 / 10082 ( 97%)
…………………………………………………..  9853 / 10082 ( 97%)
…………………………………………………..  9912 / 10082 ( 98%)
…………………………………………………..  9971 / 10082 ( 98%)
………………………………………………….. 10030 / 10082 ( 99%)
…………………………………………….        10082 / 10082 (100%)
You should really fix these slow tests (>150ms)…
1165ms to run Tests_Image_Functions:test_wp_crop_image_url
823ms to run Tests_Media:test_multiline_comment_with_embeds
425ms to run Tests_Media:test_autoembed_no_paragraphs_around_urls
413ms to run Tests_Media:test_oembed_explicit_media_link
389ms to run Tests_Dependencies_Scripts:test_no_source_mapping
377ms to run Tests_Media:test_wp_calculate_image_srcset_no_width
373ms to run Tests_Media:test_wp_calculate_image_srcset_no_date_uploads
263ms to run Tests_Import_Import:test_double_import
227ms to run Tests_Import_Import:test_small_import
214ms to run Test_Nav_Menus:test_wp_get_associated_nav_menu_items
…and there are 7 more above your threshold hidden from view 
Time: 2.07 minutes, Memory: 193.08 MB
There was 1 error:
1) Test_WP_Customize_Nav_Menus::test_search_available_items_query
There were 13 failures:
1) Tests_Date_Get_Permalink::test_should_return_correct_date_permalink_with_changed_time_zone
2) Tests_DB::test_get_col with data set #2 ('SELECT user_login, user_email…_users', 'admin@example.org', array(), 1)
3) Tests_DB::test_get_col with data set #3 ('SELECT user_login, user_email…_users', 'admin@example.org', array(), '1')
4) Tests_Dependencies_Scripts::test_wp_add_inline_script_before_after_concat_with_core_dependency
5) Tests_Meta_Query::test_meta_type_key_should_be_passed_to_meta_query
6) Tests_Query_MetaQuery::test_duplicate_posts_when_no_key
7) Tests_Query_MetaQuery::test_compare_key_regexp_rlike
8) Tests_Query_MetaQuery::test_compare_key_not_regexp
9) Tests_Query_Search::test_search_order_title_before_excerpt_and_content
10) WP_Test_REST_Posts_Controller::test_get_items_with_orderby_relevance_two_terms
11) WP_Test_REST_Users_Controller::test_get_items_orderby_name
12) WP_Test_REST_Users_Controller::test_update_item_existing_email_case_not_own
13) Tests_Term_getTerms::test_get_terms_like
ERRORS!
Tests: 10082, Assertions: 50670, Errors: 1, Failures: 13, Skipped: 44.

What do the symbols mean?

  • . Each point means that the test has been passed correctly.
  • S It means that the test has been skipped. It is usually because these tests are only valid in certain configurations.
  • F It means that the test has failed. At the end there is information about why.
  • E It means that the test has failed due to a PHP error, which can be error, warning or notice.
  • I It means that the test has been marked as incomplete.

About this document

This document is regulated by the EUPL v1.2 license, published in WP SysAdmin and created by Javier Casares. Please, if you use this content in your website, your presentation or any material you distribute, remember to mention this site or its author, and having to put the material you create under EUPL license.