FIFA WORLDCUP OFFER : 50% Off On ALL ITEMS Get It Now >

How to Build WordPress Integration Tests in CI: Complete Guide

How to Build WordPress Integration Tests in CI: Complete Guide

How to Build WordPress Integration Tests in CI: Complete Guide

Introduction

Unit tests are excellent for testing isolated PHP classes and business logic.

But WordPress plugins rarely operate in isolation.

A real plugin interacts with:

WordPress core

Database tables

Hooks and filters

Options

Metadata

REST APIs

Users and capabilities

Cron

Other plugins

Custom post types

External service boundaries

This is where WordPress integration testing becomes important.

Integration tests verify that multiple parts of your plugin actually work together inside a real WordPress test environment.

Adding those tests to Continuous Integration (CI) makes the process even more valuable. Every pull request or code change can automatically create the test environment, run the integration suite, collect failures, and prevent broken code from being merged.

A typical testing architecture looks like this:

Unit Tests     ↓ WordPress Integration Tests     ↓ Artifact / Smoke Tests     ↓ Optional E2E / Browser Tests

In this guide, you'll learn how to build WordPress integration tests with PHPUnit, Docker, a test database, and GitHub Actions.

What Is WordPress Integration Testing?

WordPress integration testing verifies that your plugin works correctly with the WordPress runtime and with the components it depends on.

Unlike a unit test, an integration test generally loads WordPress and exercises real WordPress APIs.

For example, instead of mocking get_option() completely, an integration test can:

Write an option to the WordPress test database.

Execute your plugin service.

Read the resulting option.

Verify the expected behavior.

This tests actual framework integration rather than only isolated code.

Unit Tests vs Integration Tests

The distinction is important.

Unit Tests

Unit tests focus on one class or component.

Examples:

Calculator service

Data formatter

Validation class

Repository logic with mocked dependencies

Integration Tests

Integration tests verify multiple components working together.

Examples:

Plugin service + WordPress database

Hook + service class

REST controller + authentication

Repository + $wpdb

Plugin activation + registration

WooCommerce order + analytics integration

A healthy plugin project often uses both.

Recommended CI Architecture

A practical WordPress CI environment can look like this:

GitHub Actions      ↓ Docker Test Environment      ├── WordPress      └── MySQL           ↓        Plugin           ↓   Integration Test Suite           ↓        PHPUnit           ↓      Pass / Fail

Docker helps make the environment more reproducible across developers and CI runners.

Why Run Integration Tests in CI?

Running tests only on a developer's computer creates problems.

Different developers may have different:

PHP versions

WordPress versions

Database versions

Extensions

Configuration

Dependencies

CI creates a repeatable environment.

It also ensures that integration tests run before code is merged or released.

Important CI benefits include:

Consistent environments

Automatic test execution

Early regression detection

Pull request protection

Repeatable database setup

Better release confidence

Faster feedback for developers

Step 1: Organize Your Plugin Test Structure

A clean project structure makes integration testing easier.

For example:

my-plugin/ ├── my-plugin.php ├── composer.json ├── phpunit.xml.dist ├── src/ │   ├── Service/ │   ├── Repository/ │   └── Rest/ ├── tests/ │   ├── Unit/ │   ├── Integration/ │   └── bootstrap.php ├── docker/ │   └── compose.test.yml └── .github/    └── workflows/        └── integration-tests.yml

Separating unit and integration tests allows CI to run them independently.

Step 2: Prepare the WordPress Test Environment

WordPress integration tests need a real WordPress installation and database.

Your test environment should use a dedicated test database.

Never run plugin integration tests against production data.

Typical configuration includes:

WP_TESTS_DB_NAME WP_TESTS_DB_USER WP_TESTS_DB_PASSWORD WP_TESTS_DB_HOST WP_TESTS_DIR

The exact bootstrap process can vary depending on your testing setup, WordPress version, and project tooling.

A common approach is to use the WordPress PHPUnit test suite and an installation script such as install-wp-tests.sh.

Step 3: Create a Docker Test Environment

A simplified Docker Compose configuration might look like this:

services:  wordpress:    image: wordpress:php8.2    environment:      WORDPRESS_DB_HOST: db      WORDPRESS_DB_NAME: wordpress_test      WORDPRESS_DB_USER: wordpress      WORDPRESS_DB_PASSWORD: secret    depends_on:      - db  db:    image: mysql:8.0    environment:      MYSQL_DATABASE: wordpress_test      MYSQL_USER: wordpress      MYSQL_PASSWORD: secret      MYSQL_ROOT_PASSWORD: rootsecret

For real CI usage, add health checks and wait for database readiness instead of assuming that depends_on means MySQL is already ready to accept connections.

For reproducibility, pin important image versions rather than relying on moving tags where practical.

Step 4: Bootstrap PHPUnit

WordPress integration tests commonly extend:

WP_UnitTestCase

A simple test might look like this:

final class OrderIntegrationTest extends WP_UnitTestCase {    public function test_order_event_updates_analytics(): void    {        $order_id = self::factory()->post->create(            [                'post_type' => 'shop_order',            ]        );        do_action('kdr_order_completed', $order_id);        $result = get_post_meta(            $order_id,            '_kdr_analytics_processed',            true        );        $this->assertSame('yes', $result);    } }

The exact fixture should match your plugin architecture. For WooCommerce projects, it is usually better to use WooCommerce's own object APIs and factories where available rather than treating orders as generic posts.

Step 5: Test WordPress Factories and Fixtures

Integration tests should create controlled test data.

For example:

$user_id = self::factory()->user->create(    [        'role' => 'editor',    ] ); $post_id = self::factory()->post->create(    [        'post_title' => 'Integration Test Post',        'post_status' => 'publish',    ] );

Factories make tests more readable and help reduce hard-coded IDs.

Avoid depending on IDs from another test.

Each test should create the data it needs.

Step 6: Test Plugin Hooks and Filters

Hooks are central to WordPress plugin architecture.

Suppose your plugin registers:

add_action(    'kdr_order_completed',    [ $this->analytics_service, 'record_order' ] );

You can test the integration itself:

public function test_order_completed_listener_is_registered(): void {    $this->assertNotFalse(        has_action('kdr_order_completed')    ); }

Then verify the behavior:

public function test_order_completed_event_updates_state(): void {    $order_id = self::factory()->post->create();    do_action('kdr_order_completed', $order_id);    $value = get_post_meta(        $order_id,        '_kdr_processed',        true    );    $this->assertSame('1', $value); }

For filters, use apply_filters() and assert the transformed result.

This verifies that your plugin is not merely defining classes correctly, but actually wiring those classes into WordPress.

Step 7: Test Options and Metadata

WordPress plugins frequently store settings using options and metadata.

Integration tests should verify real persistence.

update_option(    'kdr_settings',    [        'enabled' => true,        'mode'    => 'production',    ] ); $settings = get_option('kdr_settings'); $this->assertIsArray($settings); $this->assertTrue($settings['enabled']); $this->assertSame('production', $settings['mode']);

For post metadata:

$post_id = self::factory()->post->create(); update_post_meta(    $post_id,    '_kdr_status',    'active' ); $this->assertSame(    'active',    get_post_meta($post_id, '_kdr_status', true) );

These tests are useful for repositories, settings services, and persistence layers.

Step 8: Test Custom Database Tables

Plugins with custom tables should test them against a real database.

For example:

global $wpdb; $table = $wpdb->prefix . 'kdr_events'; $count = (int) $wpdb->get_var(    "SELECT COUNT(*) FROM {$table}" ); $this->assertGreaterThanOrEqual(0, $count);

More valuable integration tests should verify the complete workflow:

Service   ↓ Repository   ↓ Custom Table   ↓ Database   ↓ Repository Read   ↓ Expected Result

You should also test schema creation and upgrade paths when your plugin uses migrations.

Step 9: Test REST API Integrations

WordPress REST APIs are another important integration boundary.

A test can dispatch a real request:

$request = new WP_REST_Request(    'GET',    '/kdr/v1/orders/123' ); $response = rest_get_server()->dispatch($request); $this->assertSame(    200,    $response->get_status() );

REST tests should also verify authorization.

For example:

Authorized user → request succeeds

Unauthorized user → request rejected

Missing capability → forbidden

Invalid input → validation error

Don't test only the successful path.

Security behavior is part of integration correctness.

Step 10: Test Plugin Activation and Registration

Activation can involve:

Database schema creation

Default options

Rewrite rules

Scheduled tasks

Custom post types

Taxonomies

REST routes

Your integration suite should verify important activation behavior.

For example:

register_activation_hook(    __FILE__,    [ Plugin::class, 'activate' ] );

Then test the resulting environment rather than only checking that the PHP callback exists.

For example:

Activate Plugin      ↓ Create Tables      ↓ Create Options      ↓ Register Features      ↓ Verify Runtime State

Be cautious with activation tests because repeatedly activating a plugin inside one shared WordPress process can create state interactions. Isolated test setup is preferable.

Step 11: Test External Service Boundaries

Integration tests should not make calls to real production services.

Don't put live:

API keys

Payment credentials

OpenAI credentials

CRM credentials

Email provider credentials

into CI tests.

Instead, use:

Mocks

Stubs

Local test services

Test endpoints

Dependency injection

A useful boundary is:

WordPress   ↓ Your Service   ↓ HTTP Client Interface   ↓ Mock / Test Endpoint

This validates your plugin's integration logic without depending on an external provider being available.

Step 12: Build the GitHub Actions Workflow

A basic integration workflow can look like this:

name: WordPress Integration Tests on:  pull_request:  push: jobs:  integration:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4      - uses: shivammathur/setup-php@v2        with:          php-version: '8.2'          coverage: none      - run: composer install --no-interaction --prefer-dist      - run: docker compose -f docker/compose.test.yml up -d      - run: ./scripts/install-wp-tests.sh      - run: vendor/bin/phpunit --testsuite integration      - if: failure()        run: docker compose -f docker/compose.test.yml logs      - if: always()        run: docker compose -f docker/compose.test.yml down -v

The bootstrap command is project-specific. The WordPress test suite and related tooling can be configured in several valid ways.

The important idea is:

Checkout   ↓ Install Dependencies   ↓ Start Test Environment   ↓ Install WordPress Test Suite   ↓ Run Integration Tests   ↓ Collect Logs   ↓ Destroy Environment

Step 13: Separate Unit and Integration Jobs

As the project grows, separate the pipelines:

Pull Request     ├── Unit Tests     │      ↓     │    Fast     │     └── Integration Tests            ↓       Docker + WordPress            ↓        Quality Gate

Unit tests should generally run first because they are faster.

Integration tests can then validate framework-level behavior.

This keeps feedback fast while still protecting important integration points.

Step 14: Keep CI Test Databases Isolated

Never allow parallel CI jobs to share a mutable database.

Use:

Separate Docker environments

Separate test databases

Separate CI runners

Unique database names where necessary

Database isolation becomes especially important when your workflow tests multiple:

PHP versions

WordPress versions

MySQL versions

Plugin configurations

A failed job should not corrupt the environment used by another job.

Step 15: Test the Real Plugin Artifact

Testing source code is useful.

Testing the actual ZIP that you plan to distribute is even better.

A strong pipeline can be:

Build Plugin ZIP      ↓ Create Clean WordPress      ↓ Install ZIP Artifact      ↓ Activate Plugin      ↓ Run Integration Tests      ↓ Validate Artifact

This catches issues such as:

Missing files

Incorrect paths

Composer files omitted

Build exclusions

Broken autoloading

Missing assets

Incorrect plugin headers

For WordPress products distributed as ZIP files, artifact testing should be part of the release process.

Step 16: Add Compatibility Testing

Integration tests become even more powerful when run across a version matrix.

For example:

strategy:  matrix:    php: ['8.1', '8.2', '8.3']

You can also vary the WordPress version or supported dependency versions.

This helps detect incompatibilities before users encounter them.

Avoid creating an unnecessarily huge matrix on every pull request. A focused PR matrix plus broader scheduled or release testing can reduce CI cost.

Common WordPress Integration Testing Mistakes

Testing Only Classes

A plugin can have perfect unit tests and still fail because WordPress hooks were registered incorrectly.

Sharing Test Data

Tests that depend on another test's records become fragile.

Using Production APIs

Real external APIs make CI slow and unreliable.

Using Production Data

Never use customer or production records as fixtures.

Ignoring Database State

Persistent state can cause intermittent failures.

Hard-Coding IDs

Create users, posts, products, and other resources dynamically.

Skipping Authentication Tests

REST and admin functionality should test both allowed and rejected access.

Assuming Docker Readiness

A running container does not always mean the service is ready.

Testing Only Source Code

Your release ZIP can still contain packaging errors.

WordPress Integration Testing Checklist

Environment

 Dedicated test database

 Reproducible Docker environment

 Pinned core/tool versions where appropriate

 Database readiness checks

 No production credentials

PHPUnit

 WP_UnitTestCase integration suite

 Factories and controlled fixtures

 Independent tests

 Database-backed tests

 Hook and filter tests

WordPress

 Plugin boot process

 Options

 Metadata

 Custom tables

 REST endpoints

 Authentication

 Capabilities

 Activation behavior

CI

 GitHub Actions workflow

 Logs on failure

 Cleanup after every run

 Isolated environments

 Branch protection

Release

 Build ZIP

 Install ZIP

 Activate ZIP

 Run integration tests

 Validate final artifact

Recommended WordPress Integration Testing Architecture

For a production-grade plugin, use multiple testing layers:

                 Pull Request                      ↓             ┌──────────────────┐             │   Unit Tests      │             └────────┬─────────┘                      ↓             ┌──────────────────┐             │ Integration Tests│             │ WordPress + DB   │             └────────┬─────────┘                      ↓             ┌──────────────────┐             │ Artifact Tests   │             │ Plugin ZIP       │             └────────┬─────────┘                      ↓             ┌──────────────────┐             │ Optional E2E     │             │ Browser Tests    │             └────────┬─────────┘                      ↓                  Release

This creates a strong quality gate without forcing every test to perform the same job.

AI-Assisted WordPress Integration Testing

AI tools can help developers identify high-value integration boundaries and generate test scaffolding.

For example, AI can help detect:

Hooks that require behavioral tests

REST endpoints lacking authorization coverage

Repositories requiring database fixtures

Services that need integration coverage

Missing error-path tests

AI can also accelerate test generation and failure analysis.

However, generated tests should be reviewed carefully.

AI should not invent:

Real API credentials

Production endpoints

Sensitive test data

Incorrect WordPress lifecycle assumptions

The final test suite should reflect your actual architecture.

Why Choose ThemeKaddora?

ThemeKaddora develops WordPress-oriented digital products where reliable integration between WordPress, plugins, APIs, databases, analytics, WooCommerce, and business workflows can be critical.

For complex products, integration testing helps verify that individual modules continue to work correctly inside the real WordPress environment.

A strong CI pipeline can catch integration failures before a plugin ZIP is distributed to customers, making automated testing an important part of professional WordPress plugin engineering.

Conclusion

WordPress integration tests in CI provide a practical way to verify that your plugin works correctly with the WordPress runtime, database, hooks, REST APIs, authentication, and other important dependencies.

The strongest approach is not to replace unit tests with integration tests.

Instead, combine them.

Use unit tests for isolated logic.

Use integration tests for real WordPress behavior.

Use artifact tests to validate the actual ZIP package.

Use CI to execute the process consistently on every important code change.

A reliable workflow can be summarized as:

Build → Start Environment → Load WordPress → Run Integration Tests → Validate Artifact → Report → Clean Up

When this process becomes part of your normal development workflow, integration failures are discovered earlier, releases become safer, and large WordPress plugins become easier to maintain.

Frequently Asked Questions

What is WordPress integration testing?

WordPress integration testing verifies that plugin components work correctly together inside a real WordPress environment, including database operations, hooks, REST APIs, options, metadata, and related services.

Why should WordPress plugins use integration tests?

Integration tests catch problems that unit tests can miss, especially issues involving WordPress hooks, database state, REST routes, plugin registration, and framework behavior.

What is the difference between unit and integration tests?

Unit tests isolate a small component, while integration tests verify that multiple components work together with real dependencies such as WordPress and the database.

Can integration tests run in CI?

Yes. Integration tests can run automatically in GitHub Actions or other CI platforms using Docker and a dedicated WordPress test environment.

Can PHPUnit be used for WordPress integration tests?

Yes. WordPress plugin projects commonly use PHPUnit together with the WordPress test suite and WP_UnitTestCase for integration-oriented testing.

Why use Docker for WordPress integration testing?

Docker helps create a consistent WordPress, PHP, and database environment that can be reproduced locally and in CI.

How do I prevent test database conflicts in CI?

Give each CI job its own isolated environment or database. Do not share a mutable test database between parallel jobs.

Should I test multiple PHP versions?

Yes, when your plugin supports multiple PHP versions. A CI matrix can identify compatibility problems before release.

Should I test multiple WordPress versions?

Yes. Testing supported WordPress versions helps detect compatibility regressions, particularly for plugins that support a range of WordPress releases.

How do I handle database migrations in integration tests?

Test both fresh installation and upgrades from earlier schema states so that database changes are validated throughout the plugin lifecycle.

Why are integration tests slower than unit tests?

Integration tests load WordPress, interact with a database, and often initialize more application components, so they naturally require more resources and time than isolated unit tests.

Can WooCommerce plugins use integration tests?

Yes. WooCommerce plugins can test product, customer, order, analytics, checkout, hooks, and database workflows inside a real WooCommerce test environment.

What should happen when integration tests fail in GitHub Actions?

The CI job should fail, collect useful logs, clean up the test environment, and block the relevant quality gate or protected merge until the problem is resolved.

What makes a good WordPress integration test suite?

A good suite is isolated, deterministic, database-aware, security-conscious, reproducible, reasonably fast, and focused on important integration boundaries rather than implementation details.

Why choose Themekaddora?

Themekaddora provides lightweight, responsive, SEO-friendly WordPress themes with fast performance, WooCommerce compatibility, flexible customization, accessibility-conscious design, modern templates, regular updates, and professional support—providing a strong foundation for businesses building digital products and product-focused websites.

Comments (0)
Login or create account to leave comments

We use cookies to personalize your experience. By continuing to visit this website you agree to our use of cookies

More