Testing

Testing requirements in your WPZylos plugin.

Unit Testing

Test Setup

The package includes a test bootstrap that defines WordPress function stubs:

// tests/bootstrap.php
require_once dirname(__DIR__) . '/vendor/autoload.php';

// WordPress function stubs are defined here
if (!function_exists('__')) {
    function __(string $text, string $domain = 'default'): string {
        return $text;
    }
}

Testing RequirementsChecker

<?php

namespace MyPlugin\Tests\Unit;

use PHPUnit\Framework\TestCase;
use WPZylos\Framework\Requirements\RequirementsChecker;
use WPZylos\Framework\Requirements\Requirements\PhpVersionRequirement;
use WPZylos\Framework\Requirements\Requirements\PhpExtensionRequirement;

class RequirementsTest extends TestCase
{
    public function testPhpVersionPasses(): void
    {
        $checker = new RequirementsChecker();
        $checker->addRequirement(new PhpVersionRequirement('7.0'));

        $this->assertTrue($checker->check());
        $this->assertFalse($checker->hasFailures());
    }

    public function testPhpVersionFails(): void
    {
        $checker = new RequirementsChecker();
        $checker->addRequirement(new PhpVersionRequirement('99.0'));

        $this->assertFalse($checker->check());
        $this->assertTrue($checker->hasFailures());
        $this->assertCount(1, $checker->getErrors());
    }

    public function testExtensionLoaded(): void
    {
        $checker = new RequirementsChecker();
        $checker->addRequirement(new PhpExtensionRequirement('json'));

        $this->assertTrue($checker->check());
    }

    public function testExtensionNotLoaded(): void
    {
        $checker = new RequirementsChecker();
        $checker->addRequirement(new PhpExtensionRequirement('nonexistent_extension'));

        $this->assertFalse($checker->check());
        $this->assertStringContainsString(
            'nonexistent_extension',
            $checker->getErrors()[0]
        );
    }

    public function testMultipleFailures(): void
    {
        $checker = new RequirementsChecker();
        $checker
            ->addRequirement(new PhpVersionRequirement('99.0'))
            ->addRequirement(new PhpExtensionRequirement('fake_ext'));

        $this->assertFalse($checker->check());
        $this->assertCount(2, $checker->getErrors());
    }
}

Testing Custom Requirements

<?php

namespace MyPlugin\Tests\Unit;

use PHPUnit\Framework\TestCase;
use MyPlugin\Requirements\MysqlVersionRequirement;

class MysqlVersionRequirementTest extends TestCase
{
    public function testRequirementInterface(): void
    {
        $req = new MysqlVersionRequirement('5.7');

        $this->assertIsString($req->getName());
        $this->assertIsString($req->getErrorMessage());
        $this->assertIsBool($req->isSatisfied());
    }
}

Integration Testing

Testing with WordPress

For WordPress integration tests, use WP Test Utils:

<?php

namespace MyPlugin\Tests\Integration;

use WP_UnitTestCase;
use WPZylos\Framework\Requirements\RequirementsConfig;

class RequirementsIntegrationTest extends WP_UnitTestCase
{
    public function testConfigLoadsFromFile(): void
    {
        $checker = RequirementsConfig::fromFile(
            dirname(__DIR__, 2) . '/config/requirements.php'
        );

        $this->assertInstanceOf(
            \WPZylos\Framework\Requirements\RequirementsChecker::class,
            $checker
        );
    }

    public function testActualWordPressVersion(): void
    {
        global $wp_version;

        $checker = RequirementsConfig::fromArray([
            'min_wp_version' => '5.0',
        ]);

        // WordPress test suite runs on modern WP
        $this->assertFalse($checker->hasFailures());
    }
}

Mocking Requirements

For testing code that depends on requirements:

<?php

use WPZylos\Framework\Requirements\Contracts\RequirementInterface;

class MockFailingRequirement implements RequirementInterface
{
    public function isSatisfied(): bool
    {
        return false;
    }

    public function getErrorMessage(): string
    {
        return 'Mock requirement failed';
    }

    public function getName(): string
    {
        return 'mock_requirement';
    }
}

class MockPassingRequirement implements RequirementInterface
{
    public function isSatisfied(): bool
    {
        return true;
    }

    public function getErrorMessage(): string
    {
        return '';
    }

    public function getName(): string
    {
        return 'mock_passing';
    }
}

// Usage in tests
$checker = new RequirementsChecker();
$checker->addRequirement(new MockFailingRequirement());

$this->assertTrue($checker->hasFailures());

Running Tests

# Run all tests
composer test

# Run specific test file
vendor/bin/phpunit tests/Unit/RequirementsCheckerTest.php

# Run with coverage
vendor/bin/phpunit --coverage-html coverage/

PHPUnit Configuration

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd"
         bootstrap="tests/bootstrap.php"
         colors="true"
         cacheDirectory=".phpunit.cache">
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">tests/Unit</directory>
        </testsuite>
    </testsuites>
    <coverage>
        <include>
            <directory suffix=".php">src</directory>
        </include>
    </coverage>
</phpunit>