@mytechtoday/augment-extensions 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/augment-extensions/domain-rules/wordpress/README.md +163 -0
- package/augment-extensions/domain-rules/wordpress/module.json +32 -0
- package/augment-extensions/domain-rules/wordpress/rules/coding-standards.md +617 -0
- package/augment-extensions/domain-rules/wordpress/rules/directory-structure.md +270 -0
- package/augment-extensions/domain-rules/wordpress/rules/file-patterns.md +423 -0
- package/augment-extensions/domain-rules/wordpress/rules/gutenberg-blocks.md +493 -0
- package/augment-extensions/domain-rules/wordpress/rules/performance.md +568 -0
- package/augment-extensions/domain-rules/wordpress/rules/plugin-development.md +510 -0
- package/augment-extensions/domain-rules/wordpress/rules/project-detection.md +251 -0
- package/augment-extensions/domain-rules/wordpress/rules/rest-api.md +501 -0
- package/augment-extensions/domain-rules/wordpress/rules/security.md +564 -0
- package/augment-extensions/domain-rules/wordpress/rules/theme-development.md +388 -0
- package/augment-extensions/domain-rules/wordpress/rules/woocommerce.md +441 -0
- package/augment-extensions/domain-rules/wordpress-plugin/README.md +139 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/ajax-plugin.md +1599 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/custom-post-type-plugin.md +1727 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block-plugin.md +428 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block.md +422 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/mvc-plugin.md +1623 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/object-oriented-plugin.md +1343 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/rest-endpoint.md +734 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/settings-page-plugin.md +1350 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/simple-procedural-plugin.md +503 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/singleton-plugin.md +971 -0
- package/augment-extensions/domain-rules/wordpress-plugin/module.json +53 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/activation-hooks.md +770 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/admin-interface.md +874 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/ajax-handlers.md +629 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/asset-management.md +559 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/context-providers.md +709 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/cron-jobs.md +736 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/database-management.md +1057 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/documentation-standards.md +463 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/frontend-functionality.md +478 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/gutenberg-blocks.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/internationalization.md +416 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/migration.md +667 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/performance-optimization.md +878 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-architecture.md +693 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-structure.md +352 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/rest-api.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/scaffolding-workflow.md +624 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/security-best-practices.md +866 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing-patterns.md +1165 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing.md +414 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/vscode-integration.md +751 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/woocommerce-integration.md +949 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/wordpress-org-submission.md +458 -0
- package/augment-extensions/examples/gutenberg-block-plugin/README.md +101 -0
- package/augment-extensions/examples/gutenberg-block-plugin/examples/testimonial-block.md +428 -0
- package/augment-extensions/examples/gutenberg-block-plugin/module.json +40 -0
- package/augment-extensions/examples/rest-api-plugin/README.md +98 -0
- package/augment-extensions/examples/rest-api-plugin/examples/task-manager-api.md +1299 -0
- package/augment-extensions/examples/rest-api-plugin/module.json +40 -0
- package/augment-extensions/examples/woocommerce-extension/README.md +98 -0
- package/augment-extensions/examples/woocommerce-extension/examples/product-customizer.md +763 -0
- package/augment-extensions/examples/woocommerce-extension/module.json +40 -0
- package/augment-extensions/workflows/wordpress-plugin/README.md +232 -0
- package/augment-extensions/workflows/wordpress-plugin/ai-prompts.md +839 -0
- package/augment-extensions/workflows/wordpress-plugin/bead-decomposition-patterns.md +854 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/complete-plugin-example.md +540 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/custom-post-type-example.md +1083 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/feature-addition-workflow.md +669 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/plugin-creation-workflow.md +597 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/secure-form-handler-example.md +925 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/security-audit-workflow.md +752 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/wordpress-org-submission-workflow.md +773 -0
- package/augment-extensions/workflows/wordpress-plugin/module.json +49 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/best-practices.md +942 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/development-workflow.md +702 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/submission-workflow.md +728 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/testing-workflow.md +775 -0
- package/cli/dist/cli.js +5 -1
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/show.d.ts.map +1 -1
- package/cli/dist/commands/show.js +41 -0
- package/cli/dist/commands/show.js.map +1 -1
- package/modules.md +52 -0
- package/package.json +1 -1
|
@@ -0,0 +1,775 @@
|
|
|
1
|
+
# WordPress Plugin Testing Workflow
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This workflow guides you through setting up and running comprehensive tests for WordPress plugins using PHPUnit, WordPress Test Suite, and CI/CD integration.
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- WordPress plugin with code to test
|
|
10
|
+
- Composer installed
|
|
11
|
+
- Local WordPress development environment
|
|
12
|
+
- Basic understanding of PHPUnit
|
|
13
|
+
- Domain rules: `domain-rules/wordpress-plugin/testing-patterns.md`
|
|
14
|
+
|
|
15
|
+
## Workflow Steps
|
|
16
|
+
|
|
17
|
+
### 1. Initial Test Environment Setup
|
|
18
|
+
|
|
19
|
+
**Step 1.1: Install PHPUnit via Composer**
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Navigate to plugin directory
|
|
23
|
+
cd wp-content/plugins/your-plugin
|
|
24
|
+
|
|
25
|
+
# Initialize composer if not already done
|
|
26
|
+
composer init
|
|
27
|
+
|
|
28
|
+
# Install PHPUnit
|
|
29
|
+
composer require --dev phpunit/phpunit ^9.0
|
|
30
|
+
|
|
31
|
+
# Install WordPress test library
|
|
32
|
+
composer require --dev yoast/phpunit-polyfills
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Step 1.2: Install WordPress Test Suite**
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Install WordPress test suite
|
|
39
|
+
bash bin/install-wp-tests.sh wordpress_test root '' localhost latest
|
|
40
|
+
|
|
41
|
+
# Or for specific WordPress version
|
|
42
|
+
bash bin/install-wp-tests.sh wordpress_test root '' localhost 6.4
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Step 1.3: Create Test Bootstrap File**
|
|
46
|
+
|
|
47
|
+
```php
|
|
48
|
+
// tests/bootstrap.php
|
|
49
|
+
<?php
|
|
50
|
+
/**
|
|
51
|
+
* PHPUnit bootstrap file
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
// Composer autoloader
|
|
55
|
+
require_once dirname( dirname( __FILE__ ) ) . '/vendor/autoload.php';
|
|
56
|
+
|
|
57
|
+
// WordPress tests directory
|
|
58
|
+
$_tests_dir = getenv( 'WP_TESTS_DIR' );
|
|
59
|
+
|
|
60
|
+
if ( ! $_tests_dir ) {
|
|
61
|
+
$_tests_dir = rtrim( sys_get_temp_dir(), '/\\' ) . '/wordpress-tests-lib';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if ( ! file_exists( $_tests_dir . '/includes/functions.php' ) ) {
|
|
65
|
+
echo "Could not find $_tests_dir/includes/functions.php\n";
|
|
66
|
+
exit( 1 );
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Give access to tests_add_filter() function
|
|
70
|
+
require_once $_tests_dir . '/includes/functions.php';
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Manually load the plugin being tested
|
|
74
|
+
*/
|
|
75
|
+
function _manually_load_plugin() {
|
|
76
|
+
require dirname( dirname( __FILE__ ) ) . '/your-plugin.php';
|
|
77
|
+
}
|
|
78
|
+
tests_add_filter( 'muplugins_loaded', '_manually_load_plugin' );
|
|
79
|
+
|
|
80
|
+
// Start up the WP testing environment
|
|
81
|
+
require $_tests_dir . '/includes/bootstrap.php';
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Step 1.4: Create PHPUnit Configuration**
|
|
85
|
+
|
|
86
|
+
```xml
|
|
87
|
+
<!-- phpunit.xml.dist -->
|
|
88
|
+
<?xml version="1.0"?>
|
|
89
|
+
<phpunit
|
|
90
|
+
bootstrap="tests/bootstrap.php"
|
|
91
|
+
backupGlobals="false"
|
|
92
|
+
colors="true"
|
|
93
|
+
convertErrorsToExceptions="true"
|
|
94
|
+
convertNoticesToExceptions="true"
|
|
95
|
+
convertWarningsToExceptions="true"
|
|
96
|
+
>
|
|
97
|
+
<testsuites>
|
|
98
|
+
<testsuite name="unit">
|
|
99
|
+
<directory prefix="test-" suffix=".php">./tests/unit/</directory>
|
|
100
|
+
</testsuite>
|
|
101
|
+
<testsuite name="integration">
|
|
102
|
+
<directory prefix="test-" suffix=".php">./tests/integration/</directory>
|
|
103
|
+
</testsuite>
|
|
104
|
+
</testsuites>
|
|
105
|
+
<coverage processUncoveredFiles="true">
|
|
106
|
+
<include>
|
|
107
|
+
<directory suffix=".php">./includes</directory>
|
|
108
|
+
<directory suffix=".php">./admin</directory>
|
|
109
|
+
<directory suffix=".php">./public</directory>
|
|
110
|
+
</include>
|
|
111
|
+
<exclude>
|
|
112
|
+
<directory>./vendor</directory>
|
|
113
|
+
<directory>./tests</directory>
|
|
114
|
+
</exclude>
|
|
115
|
+
</coverage>
|
|
116
|
+
<php>
|
|
117
|
+
<env name="WP_TESTS_DIR" value="/tmp/wordpress-tests-lib" />
|
|
118
|
+
</php>
|
|
119
|
+
</phpunit>
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Step 1.5: Create Test Directory Structure**
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
mkdir -p tests/unit
|
|
126
|
+
mkdir -p tests/integration
|
|
127
|
+
mkdir -p tests/fixtures
|
|
128
|
+
mkdir -p tests/mocks
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### 2. Test-Driven Development Workflow
|
|
132
|
+
|
|
133
|
+
**Step 2.1: Write Test First (Red)**
|
|
134
|
+
|
|
135
|
+
```php
|
|
136
|
+
// tests/unit/test-feature.php
|
|
137
|
+
class Test_Feature extends WP_UnitTestCase {
|
|
138
|
+
|
|
139
|
+
public function test_feature_processes_data_correctly() {
|
|
140
|
+
$feature = new Plugin_Feature();
|
|
141
|
+
$input = array( 'key' => 'value' );
|
|
142
|
+
$expected = array( 'key' => 'processed_value' );
|
|
143
|
+
|
|
144
|
+
$result = $feature->process_data( $input );
|
|
145
|
+
|
|
146
|
+
$this->assertEquals( $expected, $result );
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Run test (should fail):
|
|
152
|
+
```bash
|
|
153
|
+
vendor/bin/phpunit tests/unit/test-feature.php
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Step 2.2: Implement Feature (Green)**
|
|
157
|
+
|
|
158
|
+
```php
|
|
159
|
+
// includes/feature.php
|
|
160
|
+
class Plugin_Feature {
|
|
161
|
+
public function process_data( $data ) {
|
|
162
|
+
return array( 'key' => 'processed_value' );
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Run test (should pass):
|
|
168
|
+
```bash
|
|
169
|
+
vendor/bin/phpunit tests/unit/test-feature.php
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Step 2.3: Refactor (Refactor)**
|
|
173
|
+
|
|
174
|
+
Improve code quality while keeping tests passing.
|
|
175
|
+
|
|
176
|
+
### 3. Running Tests During Development
|
|
177
|
+
|
|
178
|
+
**Run All Tests**:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Run all tests
|
|
182
|
+
vendor/bin/phpunit
|
|
183
|
+
|
|
184
|
+
# Run with verbose output
|
|
185
|
+
vendor/bin/phpunit --verbose
|
|
186
|
+
|
|
187
|
+
# Run with debug output
|
|
188
|
+
vendor/bin/phpunit --debug
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Run Specific Test Suites**:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Run only unit tests
|
|
195
|
+
vendor/bin/phpunit --testsuite unit
|
|
196
|
+
|
|
197
|
+
# Run only integration tests
|
|
198
|
+
vendor/bin/phpunit --testsuite integration
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**Run Specific Test Files**:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# Run specific test file
|
|
205
|
+
vendor/bin/phpunit tests/unit/test-feature.php
|
|
206
|
+
|
|
207
|
+
# Run specific test class
|
|
208
|
+
vendor/bin/phpunit --filter Test_Feature
|
|
209
|
+
|
|
210
|
+
# Run specific test method
|
|
211
|
+
vendor/bin/phpunit --filter test_feature_processes_data_correctly
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Run Tests with Coverage**:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# Generate HTML coverage report
|
|
218
|
+
vendor/bin/phpunit --coverage-html coverage/
|
|
219
|
+
|
|
220
|
+
# Generate text coverage report
|
|
221
|
+
vendor/bin/phpunit --coverage-text
|
|
222
|
+
|
|
223
|
+
# Generate coverage with minimum threshold
|
|
224
|
+
vendor/bin/phpunit --coverage-text --coverage-filter includes/ --coverage-clover coverage.xml
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### 4. Writing Different Types of Tests
|
|
228
|
+
|
|
229
|
+
**Unit Tests** (test in isolation):
|
|
230
|
+
|
|
231
|
+
```php
|
|
232
|
+
class Test_Data_Processor extends WP_UnitTestCase {
|
|
233
|
+
|
|
234
|
+
private $processor;
|
|
235
|
+
|
|
236
|
+
public function setUp(): void {
|
|
237
|
+
parent::setUp();
|
|
238
|
+
$this->processor = new Data_Processor();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
public function test_sanitizes_input() {
|
|
242
|
+
$input = '<script>alert("xss")</script>Test';
|
|
243
|
+
$expected = 'alert("xss")Test';
|
|
244
|
+
|
|
245
|
+
$result = $this->processor->sanitize( $input );
|
|
246
|
+
|
|
247
|
+
$this->assertEquals( $expected, $result );
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
**Integration Tests** (test with WordPress):
|
|
253
|
+
|
|
254
|
+
```php
|
|
255
|
+
class Test_Post_Handler_Integration extends WP_UnitTestCase {
|
|
256
|
+
|
|
257
|
+
public function test_creates_post_with_meta() {
|
|
258
|
+
$handler = new Post_Handler();
|
|
259
|
+
|
|
260
|
+
$post_id = $handler->create_post( array(
|
|
261
|
+
'title' => 'Test Post',
|
|
262
|
+
'meta' => array( 'key' => 'value' ),
|
|
263
|
+
) );
|
|
264
|
+
|
|
265
|
+
$this->assertGreaterThan( 0, $post_id );
|
|
266
|
+
$this->assertEquals( 'value', get_post_meta( $post_id, 'key', true ) );
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**AJAX Tests**:
|
|
272
|
+
|
|
273
|
+
```php
|
|
274
|
+
class Test_AJAX_Handler extends WP_Ajax_UnitTestCase {
|
|
275
|
+
|
|
276
|
+
public function test_ajax_action_success() {
|
|
277
|
+
// Set up request
|
|
278
|
+
$_POST['action'] = 'my_ajax_action';
|
|
279
|
+
$_POST['nonce'] = wp_create_nonce( 'my_nonce' );
|
|
280
|
+
$_POST['data'] = 'test_data';
|
|
281
|
+
|
|
282
|
+
// Set current user
|
|
283
|
+
wp_set_current_user( $this->factory->user->create( array( 'role' => 'administrator' ) ) );
|
|
284
|
+
|
|
285
|
+
// Make AJAX request
|
|
286
|
+
try {
|
|
287
|
+
$this->_handleAjax( 'my_ajax_action' );
|
|
288
|
+
} catch ( WPAjaxDieContinueException $e ) {
|
|
289
|
+
// Expected exception
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Assert response
|
|
293
|
+
$response = json_decode( $this->_last_response );
|
|
294
|
+
$this->assertTrue( $response->success );
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Database Tests**:
|
|
300
|
+
|
|
301
|
+
```php
|
|
302
|
+
class Test_Database_Operations extends WP_UnitTestCase {
|
|
303
|
+
|
|
304
|
+
private $table_name;
|
|
305
|
+
|
|
306
|
+
public function setUp(): void {
|
|
307
|
+
parent::setUp();
|
|
308
|
+
global $wpdb;
|
|
309
|
+
$this->table_name = $wpdb->prefix . 'custom_table';
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
public function test_inserts_data() {
|
|
313
|
+
global $wpdb;
|
|
314
|
+
|
|
315
|
+
$data = array(
|
|
316
|
+
'column1' => 'value1',
|
|
317
|
+
'column2' => 'value2',
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
$result = $wpdb->insert( $this->table_name, $data );
|
|
321
|
+
|
|
322
|
+
$this->assertNotFalse( $result );
|
|
323
|
+
$this->assertEquals( 1, $wpdb->insert_id );
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### 5. Using Test Factories
|
|
329
|
+
|
|
330
|
+
**Create Test Data**:
|
|
331
|
+
|
|
332
|
+
```php
|
|
333
|
+
class Test_With_Factories extends WP_UnitTestCase {
|
|
334
|
+
|
|
335
|
+
public function test_with_posts() {
|
|
336
|
+
// Create posts
|
|
337
|
+
$post_ids = $this->factory->post->create_many( 5 );
|
|
338
|
+
|
|
339
|
+
$this->assertCount( 5, $post_ids );
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
public function test_with_users() {
|
|
343
|
+
// Create user
|
|
344
|
+
$user_id = $this->factory->user->create( array(
|
|
345
|
+
'role' => 'editor',
|
|
346
|
+
'user_email' => 'test@example.com',
|
|
347
|
+
) );
|
|
348
|
+
|
|
349
|
+
$user = get_user_by( 'id', $user_id );
|
|
350
|
+
$this->assertEquals( 'editor', $user->roles[0] );
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
public function test_with_terms() {
|
|
354
|
+
// Create taxonomy terms
|
|
355
|
+
$term_ids = $this->factory->term->create_many( 3, array(
|
|
356
|
+
'taxonomy' => 'category',
|
|
357
|
+
) );
|
|
358
|
+
|
|
359
|
+
$this->assertCount( 3, $term_ids );
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### 6. Mocking and Stubbing
|
|
365
|
+
|
|
366
|
+
**Mock WordPress Functions**:
|
|
367
|
+
|
|
368
|
+
```php
|
|
369
|
+
class Test_With_Mocks extends WP_UnitTestCase {
|
|
370
|
+
|
|
371
|
+
public function test_with_filter_mock() {
|
|
372
|
+
// Add filter
|
|
373
|
+
add_filter( 'my_filter', function( $value ) {
|
|
374
|
+
return 'mocked_value';
|
|
375
|
+
} );
|
|
376
|
+
|
|
377
|
+
$result = apply_filters( 'my_filter', 'original_value' );
|
|
378
|
+
|
|
379
|
+
$this->assertEquals( 'mocked_value', $result );
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
public function test_with_action_mock() {
|
|
383
|
+
$called = false;
|
|
384
|
+
|
|
385
|
+
add_action( 'my_action', function() use ( &$called ) {
|
|
386
|
+
$called = true;
|
|
387
|
+
} );
|
|
388
|
+
|
|
389
|
+
do_action( 'my_action' );
|
|
390
|
+
|
|
391
|
+
$this->assertTrue( $called );
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
**Mock External APIs**:
|
|
397
|
+
|
|
398
|
+
```php
|
|
399
|
+
class Test_API_Client extends WP_UnitTestCase {
|
|
400
|
+
|
|
401
|
+
public function test_api_request() {
|
|
402
|
+
// Mock wp_remote_get
|
|
403
|
+
add_filter( 'pre_http_request', function( $preempt, $args, $url ) {
|
|
404
|
+
if ( strpos( $url, 'api.example.com' ) !== false ) {
|
|
405
|
+
return array(
|
|
406
|
+
'response' => array( 'code' => 200 ),
|
|
407
|
+
'body' => json_encode( array( 'data' => 'mocked' ) ),
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
return $preempt;
|
|
411
|
+
}, 10, 3 );
|
|
412
|
+
|
|
413
|
+
$client = new API_Client();
|
|
414
|
+
$result = $client->fetch_data();
|
|
415
|
+
|
|
416
|
+
$this->assertEquals( 'mocked', $result['data'] );
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### 7. CI/CD Integration Workflow
|
|
422
|
+
|
|
423
|
+
**Step 7.1: Create GitHub Actions Workflow**
|
|
424
|
+
|
|
425
|
+
```yaml
|
|
426
|
+
# .github/workflows/tests.yml
|
|
427
|
+
name: Tests
|
|
428
|
+
|
|
429
|
+
on:
|
|
430
|
+
push:
|
|
431
|
+
branches: [ main, develop ]
|
|
432
|
+
pull_request:
|
|
433
|
+
branches: [ main, develop ]
|
|
434
|
+
|
|
435
|
+
jobs:
|
|
436
|
+
test:
|
|
437
|
+
runs-on: ubuntu-latest
|
|
438
|
+
|
|
439
|
+
strategy:
|
|
440
|
+
matrix:
|
|
441
|
+
php: ['7.4', '8.0', '8.1', '8.2']
|
|
442
|
+
wordpress: ['6.0', '6.4', 'latest']
|
|
443
|
+
|
|
444
|
+
steps:
|
|
445
|
+
- uses: actions/checkout@v3
|
|
446
|
+
|
|
447
|
+
- name: Setup PHP
|
|
448
|
+
uses: shivammathur/setup-php@v2
|
|
449
|
+
with:
|
|
450
|
+
php-version: ${{ matrix.php }}
|
|
451
|
+
extensions: mysqli
|
|
452
|
+
coverage: xdebug
|
|
453
|
+
|
|
454
|
+
- name: Install dependencies
|
|
455
|
+
run: composer install --prefer-dist --no-progress
|
|
456
|
+
|
|
457
|
+
- name: Install WordPress Test Suite
|
|
458
|
+
run: bash bin/install-wp-tests.sh wordpress_test root root localhost ${{ matrix.wordpress }}
|
|
459
|
+
|
|
460
|
+
- name: Run tests
|
|
461
|
+
run: vendor/bin/phpunit --coverage-clover coverage.xml
|
|
462
|
+
|
|
463
|
+
- name: Upload coverage to Codecov
|
|
464
|
+
uses: codecov/codecov-action@v3
|
|
465
|
+
with:
|
|
466
|
+
files: ./coverage.xml
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
**Step 7.2: Create GitLab CI Configuration**
|
|
470
|
+
|
|
471
|
+
```yaml
|
|
472
|
+
# .gitlab-ci.yml
|
|
473
|
+
image: php:8.1
|
|
474
|
+
|
|
475
|
+
stages:
|
|
476
|
+
- test
|
|
477
|
+
|
|
478
|
+
variables:
|
|
479
|
+
MYSQL_ROOT_PASSWORD: root
|
|
480
|
+
MYSQL_DATABASE: wordpress_test
|
|
481
|
+
|
|
482
|
+
services:
|
|
483
|
+
- mysql:5.7
|
|
484
|
+
|
|
485
|
+
before_script:
|
|
486
|
+
- apt-get update -qq && apt-get install -y -qq git subversion mysql-client
|
|
487
|
+
- docker-php-ext-install mysqli
|
|
488
|
+
- curl -sS https://getcomposer.org/installer | php
|
|
489
|
+
- php composer.phar install
|
|
490
|
+
|
|
491
|
+
test:
|
|
492
|
+
stage: test
|
|
493
|
+
script:
|
|
494
|
+
- bash bin/install-wp-tests.sh wordpress_test root root mysql latest
|
|
495
|
+
- vendor/bin/phpunit --coverage-text --colors=never
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
### 8. Pre-Release Testing Checklist
|
|
499
|
+
|
|
500
|
+
**Code Quality**:
|
|
501
|
+
- [ ] All tests pass locally
|
|
502
|
+
- [ ] Code coverage > 80%
|
|
503
|
+
- [ ] No PHP errors or warnings
|
|
504
|
+
- [ ] Follows WordPress Coding Standards (WPCS)
|
|
505
|
+
- [ ] PHPStan/Psalm static analysis passes
|
|
506
|
+
|
|
507
|
+
**Functional Testing**:
|
|
508
|
+
- [ ] All features work as expected
|
|
509
|
+
- [ ] Admin interface functions correctly
|
|
510
|
+
- [ ] Frontend display works correctly
|
|
511
|
+
- [ ] AJAX requests work correctly
|
|
512
|
+
- [ ] Forms submit successfully
|
|
513
|
+
|
|
514
|
+
**Security Testing**:
|
|
515
|
+
- [ ] Nonce verification tests pass
|
|
516
|
+
- [ ] Capability check tests pass
|
|
517
|
+
- [ ] Input sanitization tests pass
|
|
518
|
+
- [ ] Output escaping tests pass
|
|
519
|
+
- [ ] SQL injection tests pass
|
|
520
|
+
- [ ] XSS tests pass
|
|
521
|
+
|
|
522
|
+
**Performance Testing**:
|
|
523
|
+
- [ ] Database queries are optimized
|
|
524
|
+
- [ ] No N+1 query problems
|
|
525
|
+
- [ ] Caching works correctly
|
|
526
|
+
- [ ] Page load time is acceptable
|
|
527
|
+
|
|
528
|
+
**Compatibility Testing**:
|
|
529
|
+
- [ ] Works with latest WordPress version
|
|
530
|
+
- [ ] Works with minimum supported WordPress version
|
|
531
|
+
- [ ] Works with PHP 7.4+
|
|
532
|
+
- [ ] Works with common themes
|
|
533
|
+
- [ ] Works with common plugins
|
|
534
|
+
|
|
535
|
+
**Accessibility Testing**:
|
|
536
|
+
- [ ] Keyboard navigation works
|
|
537
|
+
- [ ] Screen reader compatible
|
|
538
|
+
- [ ] Color contrast meets WCAG standards
|
|
539
|
+
- [ ] Forms have proper labels
|
|
540
|
+
|
|
541
|
+
### 9. Debugging Failed Tests
|
|
542
|
+
|
|
543
|
+
**Enable Debug Mode**:
|
|
544
|
+
|
|
545
|
+
```php
|
|
546
|
+
// tests/bootstrap.php
|
|
547
|
+
define( 'WP_DEBUG', true );
|
|
548
|
+
define( 'WP_DEBUG_LOG', true );
|
|
549
|
+
define( 'WP_DEBUG_DISPLAY', false );
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
**Use var_dump in Tests**:
|
|
553
|
+
|
|
554
|
+
```php
|
|
555
|
+
public function test_debug_output() {
|
|
556
|
+
$result = $this->feature->process_data( $input );
|
|
557
|
+
var_dump( $result ); // Will show in test output
|
|
558
|
+
$this->assertTrue( true );
|
|
559
|
+
}
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
**Use PHPUnit Debugging**:
|
|
563
|
+
|
|
564
|
+
```bash
|
|
565
|
+
# Run with debug output
|
|
566
|
+
vendor/bin/phpunit --debug
|
|
567
|
+
|
|
568
|
+
# Run with verbose output
|
|
569
|
+
vendor/bin/phpunit --verbose
|
|
570
|
+
|
|
571
|
+
# Stop on first failure
|
|
572
|
+
vendor/bin/phpunit --stop-on-failure
|
|
573
|
+
|
|
574
|
+
# Stop on first error
|
|
575
|
+
vendor/bin/phpunit --stop-on-error
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
**Check WordPress Debug Log**:
|
|
579
|
+
|
|
580
|
+
```bash
|
|
581
|
+
# View debug log
|
|
582
|
+
tail -f wp-content/debug.log
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
### 10. Continuous Testing Workflow
|
|
586
|
+
|
|
587
|
+
**Watch Mode** (using entr or similar):
|
|
588
|
+
|
|
589
|
+
```bash
|
|
590
|
+
# Install entr (macOS)
|
|
591
|
+
brew install entr
|
|
592
|
+
|
|
593
|
+
# Watch for changes and run tests
|
|
594
|
+
find . -name "*.php" | entr vendor/bin/phpunit
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
**Pre-Commit Hook**:
|
|
598
|
+
|
|
599
|
+
```bash
|
|
600
|
+
# .git/hooks/pre-commit
|
|
601
|
+
#!/bin/bash
|
|
602
|
+
|
|
603
|
+
echo "Running tests..."
|
|
604
|
+
vendor/bin/phpunit
|
|
605
|
+
|
|
606
|
+
if [ $? -ne 0 ]; then
|
|
607
|
+
echo "Tests failed. Commit aborted."
|
|
608
|
+
exit 1
|
|
609
|
+
fi
|
|
610
|
+
|
|
611
|
+
echo "Tests passed. Proceeding with commit."
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
## AI Prompt Templates
|
|
615
|
+
|
|
616
|
+
### Test Setup Prompt
|
|
617
|
+
|
|
618
|
+
```
|
|
619
|
+
Set up PHPUnit testing for [plugin name].
|
|
620
|
+
|
|
621
|
+
Requirements:
|
|
622
|
+
- Install PHPUnit via Composer
|
|
623
|
+
- Install WordPress Test Suite
|
|
624
|
+
- Create test bootstrap file
|
|
625
|
+
- Create PHPUnit configuration
|
|
626
|
+
- Create test directory structure (unit, integration, fixtures, mocks)
|
|
627
|
+
|
|
628
|
+
Test coverage needed:
|
|
629
|
+
- Unit tests for core logic
|
|
630
|
+
- Integration tests for WordPress integration
|
|
631
|
+
- AJAX tests for AJAX handlers
|
|
632
|
+
- Database tests for custom tables
|
|
633
|
+
|
|
634
|
+
Use WordPress test suite and mock WordPress functions where appropriate.
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
### Test Writing Prompt
|
|
638
|
+
|
|
639
|
+
```
|
|
640
|
+
Write comprehensive tests for [feature name] in [plugin name].
|
|
641
|
+
|
|
642
|
+
Test coverage:
|
|
643
|
+
- Unit tests for [list functions]
|
|
644
|
+
- Integration tests for [list WordPress integration points]
|
|
645
|
+
- Security tests for nonce verification, capability checks, sanitization, escaping
|
|
646
|
+
- Database tests for [list database operations]
|
|
647
|
+
|
|
648
|
+
Use test factories for creating test data.
|
|
649
|
+
Mock external APIs and WordPress functions where appropriate.
|
|
650
|
+
Achieve > 80% code coverage.
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
### CI/CD Setup Prompt
|
|
654
|
+
|
|
655
|
+
```
|
|
656
|
+
Set up CI/CD for [plugin name] using [GitHub Actions/GitLab CI].
|
|
657
|
+
|
|
658
|
+
Requirements:
|
|
659
|
+
- Test on PHP versions: 7.4, 8.0, 8.1, 8.2
|
|
660
|
+
- Test on WordPress versions: 6.0, 6.4, latest
|
|
661
|
+
- Run PHPUnit tests
|
|
662
|
+
- Generate code coverage report
|
|
663
|
+
- Upload coverage to Codecov
|
|
664
|
+
|
|
665
|
+
Create workflow file with proper matrix configuration.
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
## Best Practices
|
|
669
|
+
|
|
670
|
+
### DO
|
|
671
|
+
|
|
672
|
+
✅ Write tests before implementing features (TDD)
|
|
673
|
+
✅ Test one thing per test method
|
|
674
|
+
✅ Use descriptive test method names
|
|
675
|
+
✅ Use test factories for creating test data
|
|
676
|
+
✅ Mock external dependencies
|
|
677
|
+
✅ Test edge cases and error conditions
|
|
678
|
+
✅ Aim for > 80% code coverage
|
|
679
|
+
✅ Run tests before committing
|
|
680
|
+
✅ Use CI/CD for automated testing
|
|
681
|
+
✅ Keep tests fast and isolated
|
|
682
|
+
|
|
683
|
+
### DON'T
|
|
684
|
+
|
|
685
|
+
❌ Skip writing tests
|
|
686
|
+
❌ Test multiple things in one test
|
|
687
|
+
❌ Use production data in tests
|
|
688
|
+
❌ Depend on test execution order
|
|
689
|
+
❌ Leave failing tests in codebase
|
|
690
|
+
❌ Skip testing edge cases
|
|
691
|
+
❌ Commit without running tests
|
|
692
|
+
❌ Ignore code coverage metrics
|
|
693
|
+
❌ Write slow tests
|
|
694
|
+
❌ Test implementation details
|
|
695
|
+
|
|
696
|
+
## Common Testing Patterns
|
|
697
|
+
|
|
698
|
+
### Pattern 1: Test Setup and Teardown
|
|
699
|
+
|
|
700
|
+
```php
|
|
701
|
+
class Test_Feature extends WP_UnitTestCase {
|
|
702
|
+
|
|
703
|
+
private $feature;
|
|
704
|
+
private $test_post_id;
|
|
705
|
+
|
|
706
|
+
public function setUp(): void {
|
|
707
|
+
parent::setUp();
|
|
708
|
+
$this->feature = new Feature();
|
|
709
|
+
$this->test_post_id = $this->factory->post->create();
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
public function tearDown(): void {
|
|
713
|
+
wp_delete_post( $this->test_post_id, true );
|
|
714
|
+
parent::tearDown();
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
### Pattern 2: Data Providers
|
|
720
|
+
|
|
721
|
+
```php
|
|
722
|
+
class Test_Validation extends WP_UnitTestCase {
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* @dataProvider email_provider
|
|
726
|
+
*/
|
|
727
|
+
public function test_email_validation( $email, $expected ) {
|
|
728
|
+
$result = $this->validator->is_valid_email( $email );
|
|
729
|
+
$this->assertEquals( $expected, $result );
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
public function email_provider() {
|
|
733
|
+
return array(
|
|
734
|
+
array( 'valid@example.com', true ),
|
|
735
|
+
array( 'invalid@', false ),
|
|
736
|
+
array( 'no-at-sign.com', false ),
|
|
737
|
+
array( '', false ),
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
### Pattern 3: Exception Testing
|
|
744
|
+
|
|
745
|
+
```php
|
|
746
|
+
class Test_Error_Handling extends WP_UnitTestCase {
|
|
747
|
+
|
|
748
|
+
public function test_throws_exception_on_invalid_input() {
|
|
749
|
+
$this->expectException( InvalidArgumentException::class );
|
|
750
|
+
$this->expectExceptionMessage( 'Invalid input' );
|
|
751
|
+
|
|
752
|
+
$this->feature->process( null );
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
## Resources
|
|
758
|
+
|
|
759
|
+
- [WordPress PHPUnit Documentation](https://make.wordpress.org/core/handbook/testing/automated-testing/phpunit/)
|
|
760
|
+
- [PHPUnit Documentation](https://phpunit.de/documentation.html)
|
|
761
|
+
- [WordPress Test Suite](https://develop.svn.wordpress.org/trunk/tests/phpunit/)
|
|
762
|
+
- [WP_UnitTestCase Reference](https://developer.wordpress.org/reference/classes/wp_unittestcase/)
|
|
763
|
+
- [Codecov](https://codecov.io/)
|
|
764
|
+
|
|
765
|
+
## Related Workflows
|
|
766
|
+
|
|
767
|
+
- `development-workflow.md` - Feature development cycle
|
|
768
|
+
- `scaffolding-workflow.md` - Creating new plugins
|
|
769
|
+
- `submission-workflow.md` - WordPress.org submission
|
|
770
|
+
|
|
771
|
+
## Related Domain Rules
|
|
772
|
+
|
|
773
|
+
- `domain-rules/wordpress-plugin/testing-patterns.md` - Detailed testing patterns
|
|
774
|
+
- `domain-rules/wordpress-plugin/security-best-practices.md` - Security testing
|
|
775
|
+
|