doiftrue / unitest-wp-copy
Collection of WordPress core functions and classes that can be used in unit tests to simulate WordPress environment.
Requires (Dev)
- composer/installers: *
- wordpress/wordpress: 6.9.*
- dev-main
- 6.9.2.0
- 6.9.1.2
- 6.9.0.27
- 6.9.0.26
- 6.8.2.0
- 6.8.1.2
- 6.8.0.27
- 6.8.0.26
- 6.7.2.0
- 6.7.1.2
- 6.7.0.27
- 6.7.0.26
- 6.6.2.0
- 6.6.1.2
- 6.6.0.27
- 6.6.0.26
- 6.5.2.0
- 6.5.1.2
- 6.5.0.27
- 6.5.0.26
- 0.25.0
- 0.23.4
- 0.23.3
- 0.23.1
- 0.23.0
- 0.22.0
- 0.21.1
- 0.21.0
- 0.18
- 0.17
- 0.16
- 0.15
- 0.14
- 0.13
- 0.12
- 0.11
- 0.10
- 0.9
- 0.8
- 0.7
- 0.6
- 0.5
- 0.4
- 0.2
- dev-wp-6.9
- dev-wp-6.8
- dev-wp-6.7
- dev-wp-6.6
- dev-wp-6.5
This package is auto-updated.
Last update: 2026-04-21 22:56:22 UTC
README
Helper library for PHPUnit tests. It provides selected WordPress core functions and classes that can run without full WordPress bootstrap (database or external services).
The goal is to test real WP pure-PHP behavior instead of mocking everything.
Quick Example (Why This Helps)
Suppose your code builds preview URLs like this:
function build_preview_url( string $title ): string { return add_query_arg( [ 'preview' => '1', 'slug' => sanitize_title( $title ), ], 'https://example.com/post.php' ); }
Without this library, you need to mock sanitize_title() and add_query_arg(), so they do not validate real WordPress behavior.
With this library, the same test can run real implementations in plain PHPUnit:
require_once __DIR__ . '/vendor/autoload.php'; \Unitest_WP_Copy\Bootstrap::init(); $this->assertSame( 'https://example.com/post.php?preview=1&slug=hello-world', build_preview_url( 'Hello World!' ) );
Available Symbols
For the full list of available classes/functions, see:
wp-runtime/SYMBOLS-INFO.md
Quick Start
- Install a package line that matches your WordPress version line:
composer require --dev doiftrue/unitest-wp-copy:6.9.*
- Initialize the runtime in your PHPUnit bootstrap:
require_once __DIR__ . '/vendor/autoload.php'; \Unitest_WP_Copy\Bootstrap::init();
- Write unit tests where many WordPress calls do not need mocking.
Supported WordPress Lines
Use the package line that matches your WP version:
| WordPress line | Composer constraint |
|---|---|
| 6.5 | doiftrue/unitest-wp-copy:6.5.* |
| 6.6 | doiftrue/unitest-wp-copy:6.6.* |
| 6.7 | doiftrue/unitest-wp-copy:6.7.* |
| 6.8 | doiftrue/unitest-wp-copy:6.8.* |
| 6.9 | doiftrue/unitest-wp-copy:6.9.* |
Real release tags use 4 numbers, for example 6.9.0.27:
6.9is the target WordPress version line;0.27is this repository's release-script version for that line.
In Composer, use:
6.9.0.27- pin one exact release~6.9.0.27- allow conservative updates starting from this build (usually small runtime fixes)6.9.*- allow any update in the WP6.9line (new copied functions/classes may appear and affect existing tests)
Bootstrap Overrides and Shared State
Define overrides before \Unitest_WP_Copy\Bootstrap::init().
// tests/bootstrap.php define( 'ABSPATH', '/srv/wp/' ); define( 'WP_CONTENT_DIR', '/srv/wp/wp-content' ); define( 'WP_CONTENT_URL', 'https://tests.example/wp-content' ); define( 'WP_ENVIRONMENT_TYPE', 'development' ); define( 'WP_DEBUG', true ); $GLOBALS['stub_wp_options'] = (object) [ 'home' => 'https://tests.example', 'siteurl' => 'https://tests.example', 'timezone_string' => 'Europe/Berlin', 'blog_charset' => 'UTF-8', 'gmt_offset' => 2, 'use_smilies' => false, 'use_balanceTags' => true, 'WPLANG' => 'en_US', ]; require_once __DIR__ . '/vendor/autoload.php'; \Unitest_WP_Copy\Bootstrap::init();
Runtime globals initialized or updated by bootstrap (shared in one PHP process):
$GLOBALS['stub_wp_options']$GLOBALS['timestart']$_SERVER['HTTP_HOST']$blog_id$wp_plugin_paths$shortcode_tags$wp_locale$wp_post_types$wp_taxonomies$wp_filter$wp_actions$wp_filters$wp_current_filter$allowedposttags$allowedtags$allowedentitynames$allowedxmlentitynames$wpsmiliestrans$wp_smiliessearch
If a test mutates these globals/options, restore them in setUp() / tearDown().
Constants you can predefine before bootstrap (WP 6.9 line):
ABSPATH WPINC WP_CONTENT_DIR WP_CONTENT_URL WP_ENVIRONMENT_TYPE WP_START_TIMESTAMP WP_MEMORY_LIMIT WP_MAX_MEMORY_LIMIT WP_DEVELOPMENT_MODE WP_DEBUG WP_DEBUG_DISPLAY WP_DEBUG_LOG WP_CACHE SCRIPT_DEBUG MEDIA_TRASH SHORTINIT WP_PLUGIN_DIR WP_PLUGIN_URL PLUGINDIR WPMU_PLUGIN_DIR WPMU_PLUGIN_URL MUPLUGINDIR COOKIEHASH USER_COOKIE PASS_COOKIE AUTH_COOKIE SECURE_AUTH_COOKIE LOGGED_IN_COOKIE TEST_COOKIE COOKIEPATH SITECOOKIEPATH ADMIN_COOKIE_PATH PLUGINS_COOKIE_PATH COOKIE_DOMAIN RECOVERY_MODE_COOKIE FORCE_SSL_ADMIN AUTOSAVE_INTERVAL EMPTY_TRASH_DAYS WP_POST_REVISIONS WP_CRON_LOCK_TIMEOUT CUSTOM_TAGS
Copied functions are wrapped with if ( ! function_exists( '...' ) ), so you can override specific functions by defining them before bootstrap init.
Use It When / Do Not Use It When
Use it when:
- you need real behavior of selected WP functions/classes in plain PHPUnit;
- your tested code mostly depends on WP pure-PHP logic.
Do not use it when:
- you need a full WordPress runtime and bootstrap;
- your test mostly depends on real DB/network/filesystem-heavy WP behavior.
WP_Mock Integration (Optional)
If you need handler-based mocking for supported functions, install WP_Mock:
composer require --dev 10up/wp_mock
Then use WP_Mock per test:
class ExampleTest extends \PHPUnit\Framework\TestCase { protected function setUp(): void { parent::setUp(); \WP_Mock::setUp(); } protected function tearDown(): void { \WP_Mock::tearDown(); parent::tearDown(); } public function test__is_multisite_mocked() { \WP_Mock::userFunction( 'is_multisite', [ 'return' => true ] ); $this->assertTrue( is_multisite() ); } }
For mock-friendly symbols, check:
wp-runtime/SYMBOLS-INFO.md
See also: https://github.com/10up/wp_mock
Maintainers
If you maintain this repository, see the docs in docs/ (runtime, parser, config, tests, release flow).