Testing Guide
Comprehensive testing documentation for Jankx Theme.
Getting Started
Installation
# Install PHPUnit and dependencies
composer install --dev
# Verify installation
./vendor/bin/phpunit --version
Configuration
phpunit.xml:
<phpunit bootstrap="tests/bootstrap.php"
colors="true"
verbose="true">
<testsuites>
<testsuite name="Admin">
<directory>tests/Admin</directory>
</testsuite>
<testsuite name="Extensions">
<directory>tests/Extensions</directory>
</testsuite>
<testsuite name="Layouts">
<directory>tests/Layouts</directory>
</testsuite>
<testsuite name="Services">
<directory>tests/Services</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">includes</directory>
</include>
</coverage>
</phpunit>
Test Structure
tests/
├── Admin/
│ └── Handlers/
│ └── FormHandlerTest.php # Admin form handling tests
├── Extensions/
│ └── ExtensionManagerTest.php # Extension system tests
├── Layouts/
│ └── DynamicDataLayout/
│ └── LayoutRegistryTest.php # Layout registry tests
├── Services/
│ ├── Fonts/
│ │ └── FontsRepositoryTest.php # Font management tests
│ └── GutenbergServiceTest.php # Gutenberg service tests
├── Helpers/
│ └── TestCase.php # Base test case class
├── bootstrap.php # Test bootstrap
└── phpunit.xml # PHPUnit configuration
Running Tests
Run All Tests
./vendor/bin/phpunit
Run Specific Test Suite
# Admin tests only
./vendor/bin/phpunit --testsuite="Admin"
# Extension tests only
./vendor/bin/phpunit --testsuite="Extensions"
# Layout tests only
./vendor/bin/phpunit --testsuite="Layouts"
Run Specific Test Class
./vendor/bin/phpunit --filter="FormHandlerTest"
./vendor/bin/phpunit --filter="ExtensionManagerTest"
./vendor/bin/phpunit --filter="LayoutRegistryTest"
Run with Coverage
# HTML report
./vendor/bin/phpunit --coverage-html coverage/
# Text report
./vendor/bin/phpunit --coverage-text
# XML report for CI
./vendor/bin/phpunit --coverage-xml coverage/xml/
Writing Tests
Basic Test Class
<?php
namespace Tests\Admin\Handlers;
use Jankx\Admin\Handlers\FormHandler;
use Jankx\Foundation\Application;
use Tests\Helpers\TestCase;
class FormHandlerTest extends TestCase
{
protected $formHandler;
protected $app;
protected function setUp(): void
{
parent::setUp();
$this->app = new Application();
$this->formHandler = new FormHandler($this->app);
}
public function testConstructor()
{
$this->assertInstanceOf(FormHandler::class, $this->formHandler);
}
public function testHandleRequestsProcessesValidNonce()
{
// Mock WordPress nonce verification
$GLOBALS['mock_wp_verify_nonce'] = true;
$_POST = [
'jankx_action' => 'save_settings',
'jankx_nonce' => 'valid_nonce',
];
$result = $this->formHandler->handleRequests();
$this->assertTrue($result);
}
}
Using Mockery
use Mockery;
public function testExtensionActivation()
{
// Create mock extension
$mockExtension = Mockery::mock('Jankx\Extensions\AbstractExtension');
$mockExtension->shouldReceive('activate')->once();
$mockExtension->shouldReceive('getId')->andReturn('test-extension');
// Register and activate
$manager = new ExtensionManager($this->app);
$manager->add_extension('test', $mockExtension);
$manager->activate_extension('test');
$this->assertTrue($manager->is_extension_active('test'));
}
Testing with Facades
use Jankx\Facades\Config;
public function testConfigFacade()
{
// Set up facade application
Config::setFacadeApplication($this->app);
// Mock config value
$this->app->shouldReceive('get')
->with('config.framework')
->andReturn('jankx');
$this->assertEquals('jankx', Config::get('framework'));
}
Code Coverage
| Component | Tests | Coverage |
|---|---|---|
| Admin/Handlers | 15 | High |
| Extensions | 12 | Medium |
| Layouts | 14 | High |
| Services/Fonts | 15 | Medium |
| Services/Gutenberg | 11 | Medium |
| Total | 266 | Good |
Generating Reports
# Generate HTML coverage report
./vendor/bin/phpunit --coverage-html coverage/
# Open in browser
open coverage/index.html
Best Practices
- Test Naming - Use descriptive names like
testHandleRequestsReturnsFalseForInvalidNonce - Test Structure (AAA Pattern) - Arrange, Act, Assert
- One Concept Per Test - Separate concerns into different test methods
- Use Assertions Descriptively - Choose the right assertion for the job
- Clean Up Resources - Reset state in
tearDown()
Troubleshooting
Issue: A facade root has not been set
// Solution: Set facade application in setUp()
\Jankx\Facades\App::setFacadeApplication($this->app);
Issue: Call to undefined function
// Solution: Add mock to bootstrap.php
if (!function_exists('my_wp_function')) {
function my_wp_function() {
return $GLOBALS['mock_my_wp_function'] ?? null;
}
}
Issue: InvalidCountException with Mockery
// Solution: Close Mockery properly
tearDown() {
Mockery::close();
parent::tearDown();
}