-
Confirm bootstrap defines the required constant. Open tests/bootstrap.php and verify it has:
if (!defined('PRORATE_BILLING')) {
define('PRORATE_BILLING', 1);
}
Verify before writing any test that references Plugin::$settings['REPEAT_BILLING_METHOD'].
-
Create or open tests/PluginTest.php. The file must start with:
<?php
namespace Detain\MyAdminDomains\Tests;
use PHPUnit\Framework\TestCase;
use ReflectionClass;
use ReflectionMethod;
Verify the namespace matches autoload-dev in composer.json: Detain\MyAdminDomains\Tests\ → tests/.
-
Add a setUp() method initializing the two shared fixtures used across tests:
private $reflection;
private $sourceFile;
protected function setUp(): void
{
$this->reflection = new ReflectionClass(\Detain\MyAdminDomains\Plugin::class);
$this->sourceFile = dirname(__DIR__) . '/src/Plugin.php';
}
This step's output ($this->reflection, $this->sourceFile) is used by all subsequent test methods.
-
Write static property tests using direct class access — no reflection needed:
public function testModuleProperty(): void
{
$this->assertSame('domains', \Detain\MyAdminDomains\Plugin::$module);
}
Pattern: Plugin::$propertyName for $name, $description, $help, $module, $type.
-
Write $settings tests in three layers:
- Keys present:
assertArrayHasKey($key, Plugin::$settings, "Missing: {$key}") in a loop over the 16 required keys.
- Types: loop
$intKeys, $boolKeys, $strKeys with assertIsInt/assertIsBool/assertIsString.
- Values:
assertSame($expected, Plugin::$settings[$key]) for every scalar.
Verify assertCount(16, Plugin::$settings) as a guard against silent key additions.
-
Write getHooks() tests covering: return type, key names, count, callable format, and method mapping:
public function testGetHooksMethodMapping(): void
{
$hooks = \Detain\MyAdminDomains\Plugin::getHooks();
$this->assertSame('loadProcessing', $hooks['domains.load_processing'][1]);
$this->assertSame('getSettings', $hooks['domains.settings'][1]);
}
Also assert all keys start with Plugin::$module . '.'.
-
Write method signature tests using $this->reflection:
public function testLoadProcessingSignature(): void
{
$method = $this->reflection->getMethod('loadProcessing');
$this->assertTrue($method->isPublic());
$this->assertTrue($method->isStatic());
$params = $method->getParameters();
$this->assertCount(1, $params);
$this->assertSame('event', $params[0]->getName());
$this->assertSame(
'Symfony\\Component\\EventDispatcher\\GenericEvent',
$params[0]->getType()->getName()
);
}
Apply the same pattern to getSettings().
-
Write source-level checks for patterns that need framework globals at runtime:
public function testSourceReferencesFrameworkFunctions(): void
{
$source = file_get_contents($this->sourceFile);
$this->assertStringContainsString('get_module_settings(', $source);
$this->assertStringContainsString('get_module_db(', $source);
$this->assertStringContainsString('run_event(', $source);
}
Use this pattern for: email templates, history->add(, TFSmarty, ->setEnable(, ->setReactivate(, ->register().
-
Run tests and confirm green:
composer test
Expected: OK (N tests, N assertions). Fix any failures before committing.