336 lines
7.1 KiB
PHP
336 lines
7.1 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* PHPUnit testsuite for kohana application
|
||
|
*
|
||
|
* @package Kohana/Unittest
|
||
|
* @author Kohana Team
|
||
|
* @author BRMatt <matthew@sigswitch.com>
|
||
|
* @author Paul Banks
|
||
|
* @copyright (c) 2008-2009 Kohana Team
|
||
|
* @license http://kohanaphp.com/license
|
||
|
*/
|
||
|
class Kohana_Tests
|
||
|
{
|
||
|
static protected $cache = array();
|
||
|
|
||
|
/**
|
||
|
* Flag to identify whether the installed version of phpunit
|
||
|
* is greater than or equal to 3.5
|
||
|
* @var boolean
|
||
|
*/
|
||
|
static protected $phpunit_v35 = FALSE;
|
||
|
|
||
|
/**
|
||
|
* Loads test files if they cannot be found by kohana
|
||
|
* @param <type> $class
|
||
|
*/
|
||
|
static function autoload($class)
|
||
|
{
|
||
|
$file = str_replace('_', '/', $class);
|
||
|
|
||
|
if ($file = Kohana::find_file('tests', $file))
|
||
|
{
|
||
|
require_once $file;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Configures the environment for testing
|
||
|
*
|
||
|
* Does the following:
|
||
|
*
|
||
|
* * Loads the phpunit framework (for the web ui)
|
||
|
* * Restores exception phpunit error handlers (for cli)
|
||
|
* * registeres an autoloader to load test files
|
||
|
*/
|
||
|
static public function configure_environment($do_whitelist = TRUE, $do_blacklist = TRUE)
|
||
|
{
|
||
|
// During a webui request we need to manually load PHPUnit
|
||
|
if ( ! class_exists('PHPUnit_Util_Filter', FALSE) AND ! function_exists('phpunit_autoload'))
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
include_once 'PHPUnit/Autoload.php';
|
||
|
}
|
||
|
catch (ErrorException $e)
|
||
|
{
|
||
|
include_once 'PHPUnit/Framework.php';
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// Allow PHPUnit to handle exceptions and errors
|
||
|
if (Kohana::$is_cli)
|
||
|
{
|
||
|
restore_exception_handler();
|
||
|
restore_error_handler();
|
||
|
}
|
||
|
|
||
|
spl_autoload_register(array('Kohana_Tests', 'autoload'));
|
||
|
|
||
|
Kohana_Tests::$cache = (($cache = Kohana::cache('unittest_whitelist_cache')) === NULL) ? array() : $cache;
|
||
|
|
||
|
// As of PHPUnit v3.5 there are slight differences in the way files are black|whitelisted
|
||
|
self::$phpunit_v35 = function_exists('phpunit_autoload');
|
||
|
|
||
|
$config = Kohana::config('unittest');
|
||
|
|
||
|
if ($do_whitelist AND $config->use_whitelist)
|
||
|
{
|
||
|
self::whitelist();
|
||
|
}
|
||
|
|
||
|
if ($do_blacklist AND count($config['blacklist']))
|
||
|
{
|
||
|
Kohana_Tests::blacklist($config->blacklist);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Helper function to see if unittest is enabled in the config
|
||
|
*
|
||
|
* @return boolean
|
||
|
*/
|
||
|
static function enabled()
|
||
|
{
|
||
|
$p_environment = Kohana::config('unittest.environment');
|
||
|
$k_environment = Kohana::$environment;
|
||
|
|
||
|
return (is_array($p_environment) AND in_array($k_environment, $p_environment))
|
||
|
OR
|
||
|
($k_environment === $p_environment);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Creates the test suite for kohana
|
||
|
*
|
||
|
* @return PHPUnit_Framework_TestSuite
|
||
|
*/
|
||
|
static function suite()
|
||
|
{
|
||
|
static $suite = NULL;
|
||
|
|
||
|
if ($suite instanceof PHPUnit_Framework_TestSuite)
|
||
|
{
|
||
|
return $suite;
|
||
|
}
|
||
|
|
||
|
$files = Kohana::list_files('tests');
|
||
|
|
||
|
$suite = new PHPUnit_Framework_TestSuite;
|
||
|
|
||
|
self::addTests($suite, $files);
|
||
|
|
||
|
return $suite;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Add files to test suite $suite
|
||
|
*
|
||
|
* Uses recursion to scan subdirectories
|
||
|
*
|
||
|
* @param PHPUnit_Framework_TestSuite $suite The test suite to add to
|
||
|
* @param array $files Array of files to test
|
||
|
*/
|
||
|
static function addTests(PHPUnit_Framework_TestSuite $suite, array $files)
|
||
|
{
|
||
|
if (self::$phpunit_v35)
|
||
|
{
|
||
|
$filter = PHP_CodeCoverage_Filter::getInstance();
|
||
|
}
|
||
|
|
||
|
foreach ($files as $file)
|
||
|
{
|
||
|
if (is_array($file))
|
||
|
{
|
||
|
self::addTests($suite, $file);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Make sure we only include php files
|
||
|
if (is_file($file) AND substr($file, -strlen(EXT)) === EXT)
|
||
|
{
|
||
|
// The default PHPUnit TestCase extension
|
||
|
if ( ! strpos($file, 'TestCase'.EXT))
|
||
|
{
|
||
|
$suite->addTestFile($file);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
require_once($file);
|
||
|
}
|
||
|
|
||
|
if (isset($filter))
|
||
|
{
|
||
|
$filter->addFileToBlacklist($file);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PHPUnit_Util_Filter::addFileToFilter($file);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Blacklist a set of files in PHPUnit code coverage
|
||
|
*
|
||
|
* @param array A set of files to blacklist
|
||
|
*/
|
||
|
static public function blacklist(array $blacklist_items)
|
||
|
{
|
||
|
if (self::$phpunit_v35)
|
||
|
{
|
||
|
$filter = PHP_CodeCoverage_Filter::getInstance();
|
||
|
|
||
|
foreach ($blacklist_items as $item)
|
||
|
{
|
||
|
if (is_dir($item))
|
||
|
{
|
||
|
$filter->addDirectoryToBlacklist($item);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
$filter->addFileToBlacklist($item);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
foreach ($blacklist_items as $item)
|
||
|
{
|
||
|
if (is_dir($item))
|
||
|
{
|
||
|
PHPUnit_Util_Filter::addDirectoryToFilter($item);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PHPUnit_Util_Filter::addFileToFilter($item);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the whitelist
|
||
|
*
|
||
|
* If no directories are provided then the function'll load the whitelist
|
||
|
* set in the config file
|
||
|
*
|
||
|
* @param array $directories Optional directories to whitelist
|
||
|
*/
|
||
|
static public function whitelist(array $directories = NULL)
|
||
|
{
|
||
|
if (empty($directories))
|
||
|
{
|
||
|
$directories = self::get_config_whitelist();
|
||
|
}
|
||
|
|
||
|
if (count($directories))
|
||
|
{
|
||
|
foreach ($directories as & $directory)
|
||
|
{
|
||
|
$directory = realpath($directory).'/';
|
||
|
}
|
||
|
|
||
|
// Only whitelist the "top" files in the cascading filesystem
|
||
|
self::set_whitelist(Kohana::list_files('classes', $directories));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Works out the whitelist from the config
|
||
|
* Used only on the CLI
|
||
|
*
|
||
|
* @returns array Array of directories to whitelist
|
||
|
*/
|
||
|
static protected function get_config_whitelist()
|
||
|
{
|
||
|
$config = Kohana::config('unittest');
|
||
|
$directories = array();
|
||
|
|
||
|
if ($config->whitelist['app'])
|
||
|
{
|
||
|
$directories['k_app'] = APPPATH;
|
||
|
}
|
||
|
|
||
|
if ($modules = $config->whitelist['modules'])
|
||
|
{
|
||
|
$k_modules = Kohana::modules();
|
||
|
|
||
|
// Have to do this because kohana merges config...
|
||
|
// If you want to include all modules & override defaults then TRUE must be the first
|
||
|
// value in the modules array of your app/config/unittest file
|
||
|
if (array_search(TRUE, $modules, TRUE) === (count($modules) - 1))
|
||
|
{
|
||
|
$modules = $k_modules;
|
||
|
}
|
||
|
elseif (array_search(FALSE, $modules, TRUE) === FALSE)
|
||
|
{
|
||
|
$modules = array_intersect_key($k_modules, array_combine($modules, $modules));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// modules are disabled
|
||
|
$modules = array();
|
||
|
}
|
||
|
|
||
|
$directories += $modules;
|
||
|
}
|
||
|
|
||
|
if ($config->whitelist['system'])
|
||
|
{
|
||
|
$directories['k_sys'] = SYSPATH;
|
||
|
}
|
||
|
|
||
|
return $directories;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Recursively whitelists an array of files
|
||
|
*
|
||
|
* @param array $files Array of files to whitelist
|
||
|
*/
|
||
|
static protected function set_whitelist($files)
|
||
|
{
|
||
|
if (self::$phpunit_v35)
|
||
|
{
|
||
|
$filter = PHP_CodeCoverage_Filter::getInstance();
|
||
|
}
|
||
|
|
||
|
foreach ($files as $file)
|
||
|
{
|
||
|
if (is_array($file))
|
||
|
{
|
||
|
self::set_whitelist($file);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( ! isset(Kohana_Tests::$cache[$file]))
|
||
|
{
|
||
|
$relative_path = substr($file, strrpos($file, 'classes'.DIRECTORY_SEPARATOR) + 8, -strlen(EXT));
|
||
|
$cascading_file = Kohana::find_file('classes', $relative_path);
|
||
|
|
||
|
// The theory is that if this file is the highest one in the cascading filesystem
|
||
|
// then it's safe to whitelist
|
||
|
Kohana_Tests::$cache[$file] = ($cascading_file === $file);
|
||
|
}
|
||
|
|
||
|
if (Kohana_Tests::$cache[$file])
|
||
|
{
|
||
|
if (isset($filter))
|
||
|
{
|
||
|
$filter->addFileToWhitelist($file);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
PHPUnit_Util_Filter::addFileToWhitelist($file);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|