Testing
Complete guide to the GSM Middleware automated test suite, including setup, running tests, writing new tests, and the WordPress stub system.
Overview
GSM Middleware uses PHPUnit for unit testing with a custom WordPress function stub system that allows tests to run without a full WordPress installation.
Test Stack:
- PHPUnit 11.5 — Test framework
- Yoast PHPUnit Polyfills 3.x — WordPress compatibility layer
- Custom WordPress function stubs — Simulates WordPress APIs for unit testing
Version Added: 1.18.26
Quick Start
Install Dependencies
cd wp-content/plugins/gsm-middleware
composer install
Run All Tests
composer test
Run Unit Tests Only
composer test:unit
Run with Coverage
composer test:coverage
This generates an HTML coverage report in coverage/.
Test Suite Structure
tests/
├── bootstrap.php # Test bootstrap (loads stubs, configures autoloading)
├── GSM_Test_Case.php # Base test class with common assertions
├── stubs/
│ ├── wordpress-functions.php # WordPress function stubs
│ └── class-wp-rest.php # WP REST API class stubs
└── Unit/
├── Plugin_Bootstrap_Test.php
├── Security_Manager_Test.php
├── Cron_Manager_Test.php
├── Migration_Runner_Test.php
├── Schema_Verifier_Test.php
├── Inventory_Sync_Coordinator_Test.php
├── Product_Webhook_Handler_Test.php
├── PayArc_Webhook_API_Test.php
├── External_Orders_API_Test.php
├── Lookups_API_Test.php
└── ... (32 test files total)
PHPUnit Configuration
The phpunit.xml.dist file defines two test suites:
| Suite | Directory | Purpose |
|---|---|---|
| Unit | tests/Unit/ | WordPress-independent unit tests |
| Integration | tests/Integration/ | Tests requiring WordPress (future) |
Writing Tests
Base Test Class
All tests should extend GSM_Test_Case, which provides:
use GSM\Middleware\Tests\GSM_Test_Case;
class My_Feature_Test extends GSM_Test_Case
{
public function test_something(): void
{
// Arrange, Act, Assert
}
}
Available Helper Methods:
| Method | Description |
|---|---|
assertValidJson($string) | Assert a string is valid JSON |
assertDateFormat($date, $format) | Assert a date matches a format |
getProtectedProperty($object, $property) | Access protected/private properties via reflection |
callProtectedMethod($object, $method, $args) | Call protected/private methods via reflection |
Namespace Convention
Tests use PSR-4 autoloading under GSM\Middleware\Tests\:
namespace GSM\Middleware\Tests\Unit;
WordPress Function Stubs
The test bootstrap automatically loads WordPress function stubs so tests can call functions like get_option(), sanitize_text_field(), etc. without WordPress being loaded.
Available stubs include:
| Category | Functions |
|---|---|
| Options | get_option, update_option, delete_option, get_transient, set_transient, delete_transient |
| Sanitization | sanitize_text_field, sanitize_email, wp_kses_post, absint, esc_html, esc_attr, esc_url |
| User | current_user_can, get_current_user_id, wp_get_current_user |
| HTTP | wp_remote_get, wp_remote_post, wp_remote_retrieve_body, wp_remote_retrieve_response_code |
| Hooks | add_action, add_filter, do_action, apply_filters, remove_action, remove_filter |
| REST API | register_rest_route, rest_ensure_response |
| Misc | wp_json_encode, wp_generate_password, wp_hash, wp_create_nonce, is_wp_error |
WP REST API Stubs
For testing REST controllers, stubs are provided for:
WP_REST_Request— withget_param(),get_params(),get_header(),get_body(),get_json_params()WP_REST_Response— withset_status(),get_status(),get_data()WP_REST_Controller— base classWP_REST_Server— with method constants (READABLE,CREATABLE, etc.)
Example Test
namespace GSM\Middleware\Tests\Unit;
use GSM\Middleware\Tests\GSM_Test_Case;
use GSM\Middleware\Security\Security_Manager;
class Security_Manager_Test extends GSM_Test_Case
{
private Security_Manager $security_manager;
protected function setUp(): void
{
parent::setUp();
$this->security_manager = new Security_Manager();
}
public function test_encrypt_decrypt_roundtrip(): void
{
$plaintext = 'sensitive-api-key-12345';
$encrypted = $this->security_manager->encrypt($plaintext);
$this->assertNotEquals($plaintext, $encrypted);
$this->assertEquals($plaintext, $this->security_manager->decrypt($encrypted));
}
public function test_encrypt_empty_string(): void
{
$this->assertEmpty($this->security_manager->encrypt(''));
}
}
Composer Scripts
| Script | Command | Description |
|---|---|---|
test | phpunit | Run all test suites |
test:unit | phpunit --testsuite Unit | Run unit tests only |
test:coverage | phpunit --coverage-html coverage/ | Generate HTML coverage report |
Test Coverage Summary
As of v1.18.28, the test suite includes:
- 355 tests across 32 test files
- 787 assertions total
- Coverage across all major subsystems:
- Core (plugin bootstrap, constants, autoloading)
- Security (encryption, hashing, token generation)
- Database (migrations, schema verification)
- Cron (crontab generation, scheduling)
- Sync (inventory coordination, product webhooks)
- REST API (PayArc webhooks, external orders, lookups)
Related Documentation
- CI/CD Pipeline — Automated testing in Bitbucket Pipelines
- Installation — Installing development dependencies