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
Was struggling with the same issue, managed to find some historical context here: https://github.com/pixelandtonic/Craft-Release/blob/4c0e762ce014894a0f786d64afd67d0d95c25e73/app/tests/BaseTest.php