wpstarter/o-testbench-core
Core utilities for running WordPress-focused package tests with an Orchestra Testbench-style setup. Provides shared bootstrapping, environment config, and helpers to spin up a predictable app/testing container for faster, repeatable test suites.
Installation Add the package via Composer in your WordPress project:
composer require wpstarter/o-testbench-core
Publish the config (if needed):
php artisan vendor:publish --provider="WpStarter\TestbenchCore\TestbenchCoreServiceProvider"
First Test Case
Create a basic test file in tests/Feature/ (e.g., ExampleTest.php):
<?php
namespace Tests\Feature;
use Tests\TestCase;
use WP_UnitTestCase;
class ExampleTest extends TestCase {
public function test_example() {
$this->assertTrue(true);
}
}
Run Tests Execute tests via Artisan:
php artisan test
Or use WP-CLI:
wp testbench run
Bootstrapping WordPress
Use WP_UnitTestCase for WordPress-specific assertions and environment setup:
public function setUp(): void {
parent::setUp();
$this->factory = $this->make( \WP_UnitTest_Factory::class );
}
Database Testing Leverage the built-in test database:
public function test_post_creation() {
$post_id = $this->factory->post->create();
$this->assertNotFalse($post_id);
}
Hooks and Filters
Test WordPress hooks with add_filter()/add_action():
public function test_custom_filter() {
add_filter('the_title', function($title) {
return 'Modified: ' . $title;
});
$post = $this->factory->post->create(['post_title' => 'Test']);
$this->assertStringContainsString('Modified: Test', get_the_title($post));
}
Service Container Bind WordPress classes to Laravel’s container:
$this->app->bind(\WP_Query::class, function() {
return new \WP_Query();
});
Middleware Testing Test WordPress REST API routes with Laravel’s HTTP client:
public function test_rest_route() {
$response = $this->get('/wp-json/wp/v2/posts');
$response->assertStatus(200);
}
Custom Assertions
Extend WP_UnitTestCase for reusable assertions:
class CustomTestCase extends WP_UnitTestCase {
protected function assertPostExists($post_id) {
$this->assertDatabaseHas('posts', ['ID' => $post_id]);
}
}
Database Rollback
Tests run in a fresh database, but ensure setUp()/tearDown() handle rollbacks:
public function tearDown(): void {
parent::tearDown();
global $wpdb;
$wpdb->query("TRUNCATE TABLE wp_options");
}
WordPress Globals
Avoid relying on global state (e.g., $_SERVER, $_GET). Use WP_Mock or factory methods:
// Bad: $_SERVER['REQUEST_METHOD']
// Good: $this->factory->user->create(['role' => 'administrator']);
Plugin/Themes Activation
Manually activate plugins/themes in setUp():
public function setUp(): void {
parent::setUp();
$this->activatePlugin('my-plugin');
}
WP-CLI Debugging Run tests with verbose output:
wp testbench run --verbose
Xdebug
Configure php.ini for Xdebug and use XDEBUG_TRIGGER in .env.testing:
XDEBUG_TRIGGER=1
Test Isolation
Use WP_UnitTestCase::factory() to avoid shared state between tests.
Custom Factories
Extend WP_UnitTest_Factory for domain-specific models:
$this->factory->custom_model->create(['custom_field' => 'value']);
Testbench Core Hooks
Override TestbenchCoreServiceProvider to modify behavior:
public function register() {
parent::register();
$this->app->singleton(\WP_Query::class, function() {
return new CustomWPQuery();
});
}
Parallel Testing
Use php-parallel-lint or pestphp/pest-parallel for faster test suites.
How can I help you explore Laravel packages today?