Skip to content

Instantly share code, notes, and snippets.

@selvinortiz
Last active September 13, 2018 18:23
Show Gist options
  • Save selvinortiz/9605512 to your computer and use it in GitHub Desktop.
Save selvinortiz/9605512 to your computer and use it in GitHub Desktop.
Unit Testing for Craft Plugins

Unit Testing for Craft Plugins

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.

Assumed Directory Structure


@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

Other Assumptions

  • PHP 5.3.2+ is properly installed and can be called from the command line

Example Test

<?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));
	}
}

Running PHPUnit

From Terminal

This is an example to run from the command line but do note that there are other ways to do it.

Full Command

/path/to/php -c /path/to/php.ini @craftVendor/phpunit/phpunit/phpunit.php --bootstrap @craftTests/bootstrap.php --configuration @craftTests/phpunit.xml @pluginTestDir

Step By Step Command

These commands should be executed as a single command with exactly one space between each step.

Invoke the PHP executable and pass along our php.ini

php -c /etc/php5/apache2/php.ini

Run PHPUnit through PHP

/path/to/site/craft/vendor/phpunit/phpunit/phpunit.php or which phpunit

Tell PHPUnit what bootstrap file to use

--bootstrap /path/to/site/craft/app/tests/bootstrap.php

Tell PHPUnit to use the configuration file provided by Craft

--configuration /path/to/site/craft/app/tests/phpunit.xml

Finally, tell PHPUnit where to find your plugin test directory

/path/to/site/craft/plugins/yourplugin/tests

Issues

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.

Written By

Selvin Ortiz
Lead Developer
Barrel Strength Design

@dnunez24
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment