Skip to content
Development
Skill

/wp-plugin-testing

Use when writing or setting up tests for a WordPress plugin — PHPUnit integration tests using WP_UnitTestCase with the WP test suite (bin/install-wp-tests.sh, phpunit.xml.dist, tests/bootstrap.php), unit tests with Brain Monkey (when() / expect() / Mockery) or WP_Mock, test

From plugin
wp-dev-skills
2719 skills1 command
Install
$ npx -y skills add mralaminahamed/wp-dev-skills --skill wp-plugin-testing --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/wp-plugin-testing

Context preview

The summary Claude sees to decide when to auto-load this skill.

Use when writing or setting up tests for a WordPress plugin — PHPUnit integration tests using WP_UnitTestCase with the WP test suite (bin/install-wp-tests.sh, phpunit.xml.dist, tests/bootstrap.php), unit tests with Brain Monkey (when() / expect() / Mockery) or WP_Mock, test

SKILL.md

wp-plugin-testing.SKILL.md
name: wp-plugin-testing
description: "Use when writing or setting up tests for a WordPress plugin — PHPUnit integration tests using WP_UnitTestCase with the WP test suite (bin/install-wp-tests.sh, phpunit.xml.dist, tests/bootstrap.php), unit tests with Brain Monkey (when() / expect() / Mockery) or WP_Mock, test factories (factory()->post->create(), ->user->create(), ->term->create()), HTTP request mocking with add_filter pre_http_request, AJAX testing with WP_Ajax_UnitTestCase, redirect/exit testing via exception-throwing pattern, multisite tests (WP_MULTISITE=1), acceptance tests with Codeception + wp-browser, or GitHub Actions CI matrix for PHP x WP versions. Triggers: \"write a test for this\", \"unit test this function\", \"set up PHPUnit for my plugin\", \"mock this WP function\", \"Brain Monkey setup\", \"WP_Mock\", \"test is failing\", \"how do I test a hook\", \"test my REST endpoint\", \"factory()->post->create()\", \"install the WP test suite\", \"test my wp_mail call\", \"integration test setup\", \"bin/install-wp-tests.sh\", \"phpunit.xml.dist\", \"WP_UnitTestCase\", \"WP_Ajax_UnitTestCase\", \"pre_http_request mock\", \"test a redirect\", \"WP_MULTISITE=1 test\", \"Codeception wp-browser\", \"Brain Monkey setUp tearDown\", \"PHP x WP version matrix in CI\", \"test a wp_schedule_event\", \"assert hook was called\". Not for: E2E browser tests — use `wp-admin-browser` for those."

WordPress Plugin Testing

> **Model note:** Bootstrap and CI config setup are mechanical (`haiku`). Writing meaningful test cases (choosing fixtures, mocking the right layer, testing edge cases) requires understanding the plugin's code — use `sonnet`. Redirect/exit harness setup is a one-time pattern and works on `haiku`.

Set up and write automated tests for WordPress plugins: PHPUnit integration tests (real WP + DB), pure unit tests (no WP loaded), and acceptance/E2E tests with Codeception.

When to use

  • "Set up PHPUnit tests for my plugin", "bootstrap a WP test suite", "scaffold plugin tests".
  • "Write a unit test for this function", "mock WordPress functions without loading WP".
  • "Set up Codeception / wp-browser", "write acceptance tests".
  • "Test a hook callback", "assert a filter changes the output", "test AJAX handlers".
  • "Add tests to CI", "run tests on GitHub Actions".

**Not for:** PHPStan static analysis — use the official `wp-phpstan` skill. Scaffolding a stubs package for a third-party library — use `wp-phpstan-stubs`. Debugging CI failures on an existing suite — use `wp-ci-qa`.

Method

1. Choose test type

| Type | Tool | WP loaded | DB | Speed | |---|---|---|---|---| | Integration | PHPUnit + WP test suite (`WP_UnitTestCase`) | ✅ Full | ✅ Real (temp) | Slow | | Unit | PHPUnit + Brain\Monkey (recommended) or WP_Mock | ❌ | ❌ | Fast | | Acceptance | Codeception + wp-browser | ✅ Browser | ✅ Real | Slowest |

Start with integration tests for hooks/filters; unit tests for pure business logic; acceptance only for critical user flows.

2. Integration test setup (WP test suite)

**Install test suite:**

# WP-CLI method (recommended)
wp scaffold plugin-tests my-plugin

# Manual — install WP test library
bash bin/install-wp-tests.sh wordpress_test root '' localhost latest

`bin/install-wp-tests.sh` creates a temp WP installation and the `wordpress-tests-lib`. Add `tests/` dir to `.gitignore` if downloading WP inline, or commit the bootstrap only.

**`composer.json` additions:**

{
    "require-dev": {
        "phpunit/phpunit": "^9.0 || ^10.0",
        "yoast/phpunit-polyfills": "^2.0"
    },
    "scripts": {
        "test": "phpunit",
        "test:unit": "phpunit --testsuite=unit",
        "test:integration": "phpunit --testsuite=integration"
    }
}

**`phpunit.xml.dist`:**

<?xml version="1.0"?>
<phpunit bootstrap="tests/bootstrap.php" colors="true">
    <testsuites>
        <testsuite name="integration">
            <directory>tests/integration</directory>
        </testsuite>
        <testsuite name="unit">
            <directory>tests/unit</directory>
        </testsuite>
    </testsuites>
</phpunit>

**`tests/bootstrap.php` (integration):**

<?php
$_tests_dir = getenv( 'WP_TESTS_DIR' ) ?: '/tmp/wordpress-tests-lib';
require_once $_tests_dir . '/includes/functions.php';

tests_add_filter( 'muplugins_loaded', function() {
    require dirname( __DIR__ ) . '/my-plugin.php';
} );

require $_tests_dir . '/includes/bootstrap.php';

3. Write integration tests

Extend `WP_UnitTestCase` (provided by WP test suite). It wraps each test in a DB transaction and rolls back — no teardown needed for posts/users/terms.

class Test_My_Feature extends WP_UnitTestCase {

    public function test_filter_changes_title() {
        $post_id = self::factory()->post->create( [ 'post_title' => 'Original' ] );

        // Activate the plugin feature
        add_filter( 'the_title', 'my_plugin_modify_title', 10, 2 );

        $title = get_the_title( $post_id );

        $this->assertStringContainsString( 'Modified', $title );
    }

    public function test_option_saved_on_activation() {
        do_action( 'activate_my-plugin/my-plugin.php' );

        $this->assertSame( '1.0.0', get_option( 'my_plugin_version' ) );
    }

    public function test_ajax_handler_returns_json() {
        // Simulate AJAX call
        $_POST['_wpnonce'] = wp_create_nonce( 'my_action' );
        $_POST['data']     = 'test';

        try {
            $this->_handleAjax( 'my_plugin_action' );
        } catch ( WPAjaxDieContinueException $e ) {
            // Normal for wp_send_json_success
        }

        $response = json_decode( $this->_last_response, true );
        $this->assertTrue( $response['success'] );
    }
}

**Factory helpers:**

$user_id    = self::factory()->user->create( [ 'role' => 'editor' ] );
$term_id    = self::factory()->term->create( [ 'taxonomy' => 'category', 'name' => 'News' ] );
$post_ids   = self::factory()->post->create_m
Read more
Ships withwp-dev-skills

Covers the complete WordPress plugin development lifecycle — build, test, audit, release, and ship to WP.org — for Claude Code, Gemini CLI, Cursor, Windsurf, Cline, Codex, GitHub Copilot, opencode, and more.

Get the whole plugin
Stats
27
Stars
3
Forks
Maintained
Maintenance
PHP
Language
MIT
License
1mo ago
Last commit
3mo ago
Created

Repo: mralaminahamed/wp-dev-skills

Other skills on wp-dev-skills.