Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Wp Test Utils Laravel Package

yoast/wp-test-utils

Yoast WP Test Utils provides PHPUnit test case classes and helpers for WordPress plugins and themes, making it easier to write reliable unit and integration tests with proper WordPress bootstrapping and mocking.

View on GitHub
Deep Wiki
Context7

Getting Started

yoast/wp-test-utils is not a Laravel package — it is a thin, opinionated compatibility layer that sits between your test file and either (a) the WordPress core test suite or (b) Brain Monkey. For a Laravel developer the realistic entry points are narrow:

  • You maintain a WP plugin/theme in the same monorepo as a Laravel app.
  • You ship a Laravel package that bridges to WordPress (headless WP, WP REST client, shared domain code).
  • You are testing PHP code that calls WP globals (get_option, wp_remote_get, apply_filters) and want it green in CI without booting WordPress.

Install it as a dev dependency and keep it in its own test suite:

composer require --dev yoast/wp-test-utils
composer require --dev brain/monkey   # only if you want the unit-test flavour

Where to look first, in order:

  1. src/BrainMonkey/TestCase.php — the base class for unit tests. It wires up Brain\Monkey\setUp()/tearDown() for you.
  2. src/WPIntegration/TestCase.php — the replacement for WP_UnitTestCase that smooths over set_up() vs setUp() and PHPUnit 5→10 differences.
  3. src/Helpers/ExpectOutputHelper.php — expectOutputString()/expectOutputRegex() for PHPUnit versions where output expectations were removed.
  4. src/WPIntegration/bootstrap-functions.php — path resolution helpers for locating the WP test library.

The fastest first win is converting one brittle unit test. Take a class that calls get_option() and apply_filters(), extend Yoast\WPTestUtils\BrainMonkey\TestCase, and stub those globals with Brain Monkey. No database, no WordPress bootstrap, milliseconds per test. Do that before touching integration tests — the integration path requires a real MySQL database and the WP core test suite checked out somewhere.

Realistic expectation-setting: 62 stars and zero Packagist dependents means you are on a lightly-trodden path. Yoast's own plugin repos consume it, but you will not find a large Stack Overflow corpus. Budget time to read src/ — it is small enough to read end-to-end in twenty minutes, which is the best documentation you will get.

Implementation Patterns

Unit tests with Brain Monkey. The base class handles lifecycle, so your test only contains expectations:

use Yoast\WPTestUtils\BrainMonkey\TestCase;
use Brain\Monkey\Functions;

final class OptionsTest extends TestCase {
    protected function set_up(): void {
        parent::set_up();               // snake_case, not setUp()
        Functions\when('is_admin')->justReturn(false);
        Functions\expect('get_option')
            ->once()
            ->with('my_plugin_settings', [])
            ->andReturn(['enabled' => true]);
    }

    public function test_reads_settings(): void {
        self::assertTrue((new Settings())->enabled());
    }
}

This is the direct analogue of Laravel's Http::fake() / Facade::shouldReceive() but for global functions — which is the only mocking surface WP code gives you.

Integration tests. Extend Yoast\WPTestUtils\WPIntegration\TestCase instead of WP_UnitTestCase. You get the WP factories (self::factory()->post->create()), go_to(), set_current_user(), and transactional rollback per test. The value over vanilla WP_UnitTestCase is that the same test file works across WP 5.x → 6.x and PHPUnit 7 → 10 without conditional method_exists( $this, 'set_up' ) shims in your own code.

Bootstrap layout. Put a tests/phpunit/bootstrap.php that requires Composer's autoloader, then loads the WP test library (includes/functions.php, includes/bootstrap.php) using the path helpers the package provides. Do not try to reuse Laravel's bootstrap/app.php here — see gotchas.

Pest. You can register the base class per-directory:

uses(Yoast\WPTestUtils\BrainMonkey\TestCase::class)->in('tests/Unit/WordPress');

CI matrix. The whole point of the package is cross-version safety, so pin a GitHub Actions matrix on PHP × WP version × PHPUnit version. Use yoast/phpunit-polyfills (a transitive dependency) assertions — assertIsArray, assertObjectHasProperty — and avoid raw PHPUnit APIs that were renamed between majors. If you are testing a plugin, download the matching wordpress-develop tag per matrix cell rather than testing against trunk only.

Where it composes with a Laravel codebase. Keep the WP suite as a separate Composer autoload namespace and a separate phpunit-wp.xml. Shared domain classes can then be tested twice: once under orchestra/testbench against Laravel facades, once under Brain Monkey against WP globals, with the same assertions. That dual harness is the main reason a Laravel developer would reach for this package at all.

Gotchas and Tips

  • set_up() vs setUp() is the number one footgun. Both base classes expect you to override the snake_case WP naming. If you override setUp() instead, you silently skip Brain Monkey bootstrapping or the polyfill bridge, and you get "function already defined" or "undefined function" errors that point nowhere useful. Always call parent::set_up().
  • Bootstrap ordering is absolute. WP's test bootstrap defines ABSPATH, WP_DEBUG, and loads wp-settings.php. It must run before any of your WP-facing classes are autoloaded, and it cannot coexist in the same PHP process as a booted Laravel application. Run them as separate CI jobs or separate phpunit invocations — never a single suite with both.
  • Brain Monkey does not work against loaded WordPress. If wp-includes/plugin.php is already loaded, Brain Monkey cannot redefine those functions. Use BrainMonkey\TestCase for pure unit tests and WPIntegration\TestCase for anything that needs real WP behaviour. There is no useful middle ground.
  • TestCaseNoPolyfills exists for a reason. If your project (or another dev dependency) already loads yoast/phpunit-polyfills, using the standard integration TestCase produces duplicate function declarations. Switch to Yoast\WPTestUtils\WPIntegration\TestCaseNoPolyfills and load the polyfills once yourself.
  • MySQL is mandatory for integration tests. There is no SQLite path out of the box; you need a database, WP_TESTS_DOMAIN, and the WP test library on disk. Most cryptic failures ("Cannot find WordPress installation") are just an unset WP_TESTS_DIR/WP_DEVELOP_DIR or a path helper resolving relative to the wrong directory. Add a var_dump() of the resolved path in bootstrap once; it will save an hour later.
  • Global function autoloading is a side effect. The package ships bootstrap functions via Composer files autoload. In a large monorepo that means they are always in scope — check for function-name collisions if you also ship your own src/functions.php helpers.
  • PHPUnit 10+ attributes. Annotation-based @dataProvider is deprecated/removed in newer PHPUnit; the package follows polyfill conventions, so migrate providers to #[DataProvider('...')] attributes if your matrix includes PHPUnit 10, or keep the matrix capped at 9.
  • Extension points are plain subclassing. Override set_up()/tear_down(), add helper assertions in a project-level abstract TestCase, or use Yoast\WPTestUtils\BrainMonkey\YoastTestCase as a starting point if you want the Yoast-flavoured expectation helpers. There is no service container, no config file, no plugin system — which is a feature: reading src/ tells you everything.
  • Pin the version and watch PHP constraints. The package lags the newest PHPUnit/PHP releases by design (its job is supporting the old ones). A composer update that bumps it can change which polyfill shims are loaded and flip previously-green tests. Lock it in composer.json alongside your PHPUnit constraint.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route