Writing unit tests for your craft plugin has not been straight forward out of the gate but P&T is taking steps to fully integrate unit testing and have already added the basic necessities to do so.
@craft = /path/to/site/craft
@craftTests = @craft/app/tests
@craftVendor = @craft/app/vendor
@craftPlugins = @craft/plugins
@pluginTestDir = @craft/plugins/yourplugin/tests
/path/to/site/craft
- /app
- /tests
- /vendor
- /plugins
- plugin
- tests
- PHP 5.3.2+ is properly installed and can be called from the command line
<?php
namespace Craft;
use \Mockery as m;
class PluginTest extends BaseTest
{
protected $config;
protected $service;
public function setUp()
{
$this->config = m::mock('Craft\ConfigService');
$this->config->shouldReceive('getIsInitialized')->andReturn(true);
$this->config->shouldReceive('usePathInfo')->andReturn(true)->byDefault();
$this->config->shouldReceive('get')->with('usePathInfo')->andReturn(true)->byDefault();
$this->config->shouldReceive('get')->with('cpTrigger')->andReturn('admin')->byDefault();
$this->config->shouldReceive('get')->with('pageTrigger')->andReturn('p')->byDefault();
$this->config->shouldReceive('get')->with('actionTrigger')->andReturn('action')->byDefault();
$this->config->shouldReceive('get')->with('translationDebugOutput')->andReturn(false)->byDefault();
$this->config->shouldReceive('getLocalized')->with('loginPath')->andReturn('login')->byDefault();
$this->config->shouldReceive('getLocalized')->with('logoutPath')->andReturn('logout')->byDefault();
$this->config->shouldReceive('getLocalized')->with('setPasswordPath')->andReturn('setpassword')->byDefault();
$this->config->shouldReceive('getCpLoginPath')->andReturn('login')->byDefault();
$this->config->shouldReceive('getCpLogoutPath')->andReturn('logout')->byDefault();
$this->config->shouldReceive('getCpSetPasswordPath')->andReturn('setpassword')->byDefault();
$this->config->shouldReceive('getResourceTrigger')->andReturn('resource')->byDefault();
$this->setComponent(craft(), 'config', $this->config);
$this->setEnvironment();
$this->loadServices();
}
public function testGetRequestIp()
{
$this->assertEquals($_SERVER['REMOTE_ADDR'], '127.0.0.1');
}
protected function setEnvironment()
{
$this->settings = m::mock('Craft\Model');
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
}
protected function loadServices()
{
require_once __DIR__ . '/../services/PluginService.php';
$this->service = new PluginService();
}
protected function inspect($data)
{
fwrite(STDERR, print_r($data));
}
}
This is an example to run from the command line but do note that there are other ways to do it.
/path/to/php -c /path/to/php.ini @craftVendor/phpunit/phpunit/phpunit.php --bootstrap @craftTests/bootstrap.php --configuration @craftTests/phpunit.xml @pluginTestDir
These commands should be executed as a single command with exactly one space between each step.
php -c /etc/php5/apache2/php.ini
/path/to/site/craft/vendor/phpunit/phpunit/phpunit.php
or which phpunit
--bootstrap /path/to/site/craft/app/tests/bootstrap.php
--configuration /path/to/site/craft/app/tests/phpunit.xml
/path/to/site/craft/plugins/yourplugin/tests
The biggest issues I've come across during testing have to do with bootstrapping dependencies.
Some issues are really hard to diagnose and explain and in effort to keep this short... I figured that rather than explaining every single issue I've found, I'd just post what is currently working for me and other's I've helped and if you can't get things running just post a comment here and we can sort it out together.
Selvin Ortiz
Lead Developer
Barrel Strength Design
There appears to be a typo in your example method loadServices(), the service name is PluginsService (double sS), had to fix the path in line 50 and then the instantiation at line 52.