Refactored TestRunner and core
This commit is contained in:
parent
c7250ae0a9
commit
22b18bfbc9
8 changed files with 450 additions and 383 deletions
144
src/core.php
144
src/core.php
|
@ -19,20 +19,23 @@ require_once $rootDir . 'lib' . DS . 'chibi-core' . DS . 'include.php';
|
||||||
|
|
||||||
require_once $rootDir . 'src' . DS . 'routes.php';
|
require_once $rootDir . 'src' . DS . 'routes.php';
|
||||||
|
|
||||||
function getConfig()
|
final class Core
|
||||||
{
|
{
|
||||||
global $config;
|
private static $context;
|
||||||
return $config;
|
private static $config;
|
||||||
}
|
|
||||||
|
|
||||||
function getContext()
|
static function getConfig()
|
||||||
{
|
{
|
||||||
global $context;
|
return self::$config;
|
||||||
return $context;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function prepareConfig($testEnvironment)
|
static function getContext()
|
||||||
{
|
{
|
||||||
|
return self::$context;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function prepareConfig($testEnvironment)
|
||||||
|
{
|
||||||
//load config manually
|
//load config manually
|
||||||
global $config;
|
global $config;
|
||||||
global $rootDir;
|
global $rootDir;
|
||||||
|
@ -48,22 +51,21 @@ function prepareConfig($testEnvironment)
|
||||||
$configPaths []= $rootDir . DS . 'tests' . DS . 'config.ini';
|
$configPaths []= $rootDir . DS . 'tests' . DS . 'config.ini';
|
||||||
}
|
}
|
||||||
|
|
||||||
$config = new \Chibi\Config();
|
self::$config = new \Chibi\Config();
|
||||||
foreach ($configPaths as $path)
|
foreach ($configPaths as $path)
|
||||||
if (file_exists($path))
|
if (file_exists($path))
|
||||||
$config->loadIni($path);
|
self::$config->loadIni($path);
|
||||||
$config->rootDir = $rootDir;
|
self::$config->rootDir = $rootDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareEnvironment($testEnvironment)
|
static function prepareEnvironment($testEnvironment)
|
||||||
{
|
{
|
||||||
//prepare context
|
//prepare context
|
||||||
global $context;
|
|
||||||
global $startTime;
|
global $startTime;
|
||||||
$context = new StdClass;
|
self::$context = new StdClass;
|
||||||
$context->startTime = $startTime;
|
self::$context->startTime = $startTime;
|
||||||
|
|
||||||
$config = getConfig();
|
$config = self::getConfig();
|
||||||
|
|
||||||
TransferHelper::createDirectory($config->main->filesPath);
|
TransferHelper::createDirectory($config->main->filesPath);
|
||||||
TransferHelper::createDirectory($config->main->thumbsPath);
|
TransferHelper::createDirectory($config->main->thumbsPath);
|
||||||
|
@ -89,7 +91,103 @@ function prepareEnvironment($testEnvironment)
|
||||||
TextHelper::absolutePath($config->main->dbLocation),
|
TextHelper::absolutePath($config->main->dbLocation),
|
||||||
isset($config->main->dbUser) ? $config->main->dbUser : null,
|
isset($config->main->dbUser) ? $config->main->dbUser : null,
|
||||||
isset($config->main->dbPass) ? $config->main->dbPass : null);
|
isset($config->main->dbPass) ? $config->main->dbPass : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function getDbVersion()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$dbVersion = PropertyModel::get(PropertyModel::DbVersion);
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
return [null, null];
|
||||||
|
}
|
||||||
|
if (strpos($dbVersion, '.') !== false)
|
||||||
|
{
|
||||||
|
list ($dbVersionMajor, $dbVersionMinor) = explode('.', $dbVersion);
|
||||||
|
}
|
||||||
|
elseif ($dbVersion)
|
||||||
|
{
|
||||||
|
$dbVersionMajor = $dbVersion;
|
||||||
|
$dbVersionMinor = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$dbVersionMajor = 0;
|
||||||
|
$dbVersionMinor = 0;
|
||||||
|
}
|
||||||
|
return [$dbVersionMajor, $dbVersionMinor];
|
||||||
|
}
|
||||||
|
|
||||||
|
static function upgradeDatabase()
|
||||||
|
{
|
||||||
|
$config = self::getConfig();
|
||||||
|
$upgradesPath = TextHelper::absolutePath($config->rootDir
|
||||||
|
. DS . 'src' . DS . 'Upgrades' . DS . $config->main->dbDriver);
|
||||||
|
|
||||||
|
$upgrades = glob($upgradesPath . DS . '*.sql');
|
||||||
|
natcasesort($upgrades);
|
||||||
|
|
||||||
|
foreach ($upgrades as $upgradePath)
|
||||||
|
{
|
||||||
|
preg_match('/(\d+)\.sql/', $upgradePath, $matches);
|
||||||
|
$upgradeVersionMajor = intval($matches[1]);
|
||||||
|
|
||||||
|
list ($dbVersionMajor, $dbVersionMinor) = self::getDbVersion();
|
||||||
|
|
||||||
|
if (($upgradeVersionMajor > $dbVersionMajor)
|
||||||
|
or ($upgradeVersionMajor == $dbVersionMajor and $dbVersionMinor !== null))
|
||||||
|
{
|
||||||
|
printf('%s: executing' . PHP_EOL, $upgradePath);
|
||||||
|
$upgradeSql = file_get_contents($upgradePath);
|
||||||
|
$upgradeSql = preg_replace('/^[ \t]+(.*);/m', '\0--', $upgradeSql);
|
||||||
|
$queries = preg_split('/;\s*[\r\n]+/s', $upgradeSql);
|
||||||
|
$queries = array_map('trim', $queries);
|
||||||
|
$queries = array_filter($queries);
|
||||||
|
$upgradeVersionMinor = 0;
|
||||||
|
foreach ($queries as $query)
|
||||||
|
{
|
||||||
|
$query = preg_replace('/\s*--(.*?)$/m', '', $query);
|
||||||
|
++ $upgradeVersionMinor;
|
||||||
|
if ($upgradeVersionMinor > $dbVersionMinor)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
\Chibi\Database::execUnprepared(new \Chibi\Sql\RawStatement($query));
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
echo $e . PHP_EOL;
|
||||||
|
echo $query . PHP_EOL;
|
||||||
|
die;
|
||||||
|
}
|
||||||
|
PropertyModel::set(PropertyModel::DbVersion, $upgradeVersionMajor . '.' . $upgradeVersionMinor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PropertyModel::set(PropertyModel::DbVersion, $upgradeVersionMajor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf('%s: no need to execute' . PHP_EOL, $upgradePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
list ($dbVersionMajor, $dbVersionMinor) = self::getDbVersion();
|
||||||
|
printf('Database version: %d.%d' . PHP_EOL, $dbVersionMajor, $dbVersionMinor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareConfig(false);
|
//legacy
|
||||||
prepareEnvironment(false);
|
function getConfig()
|
||||||
|
{
|
||||||
|
return Core::getConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContext()
|
||||||
|
{
|
||||||
|
return Core::getContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
Core::prepareConfig(false);
|
||||||
|
Core::prepareEnvironment(false);
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
<?php
|
|
||||||
function getDbVersion()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$dbVersion = PropertyModel::get(PropertyModel::DbVersion);
|
|
||||||
}
|
|
||||||
catch (Exception $e)
|
|
||||||
{
|
|
||||||
return [null, null];
|
|
||||||
}
|
|
||||||
if (strpos($dbVersion, '.') !== false)
|
|
||||||
{
|
|
||||||
list ($dbVersionMajor, $dbVersionMinor) = explode('.', $dbVersion);
|
|
||||||
}
|
|
||||||
elseif ($dbVersion)
|
|
||||||
{
|
|
||||||
$dbVersionMajor = $dbVersion;
|
|
||||||
$dbVersionMinor = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$dbVersionMajor = 0;
|
|
||||||
$dbVersionMinor = 0;
|
|
||||||
}
|
|
||||||
return [$dbVersionMajor, $dbVersionMinor];
|
|
||||||
}
|
|
||||||
|
|
||||||
function upgradeDatabase()
|
|
||||||
{
|
|
||||||
$config = getConfig();
|
|
||||||
$upgradesPath = TextHelper::absolutePath($config->rootDir
|
|
||||||
. DS . 'src' . DS . 'Upgrades' . DS . $config->main->dbDriver);
|
|
||||||
|
|
||||||
$upgrades = glob($upgradesPath . DS . '*.sql');
|
|
||||||
natcasesort($upgrades);
|
|
||||||
|
|
||||||
foreach ($upgrades as $upgradePath)
|
|
||||||
{
|
|
||||||
preg_match('/(\d+)\.sql/', $upgradePath, $matches);
|
|
||||||
$upgradeVersionMajor = intval($matches[1]);
|
|
||||||
|
|
||||||
list ($dbVersionMajor, $dbVersionMinor) = getDbVersion();
|
|
||||||
|
|
||||||
if (($upgradeVersionMajor > $dbVersionMajor)
|
|
||||||
or ($upgradeVersionMajor == $dbVersionMajor and $dbVersionMinor !== null))
|
|
||||||
{
|
|
||||||
printf('%s: executing' . PHP_EOL, $upgradePath);
|
|
||||||
$upgradeSql = file_get_contents($upgradePath);
|
|
||||||
$upgradeSql = preg_replace('/^[ \t]+(.*);/m', '\0--', $upgradeSql);
|
|
||||||
$queries = preg_split('/;\s*[\r\n]+/s', $upgradeSql);
|
|
||||||
$queries = array_map('trim', $queries);
|
|
||||||
$queries = array_filter($queries);
|
|
||||||
$upgradeVersionMinor = 0;
|
|
||||||
foreach ($queries as $query)
|
|
||||||
{
|
|
||||||
$query = preg_replace('/\s*--(.*?)$/m', '', $query);
|
|
||||||
++ $upgradeVersionMinor;
|
|
||||||
if ($upgradeVersionMinor > $dbVersionMinor)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
\Chibi\Database::execUnprepared(new \Chibi\Sql\RawStatement($query));
|
|
||||||
}
|
|
||||||
catch (Exception $e)
|
|
||||||
{
|
|
||||||
echo $e . PHP_EOL;
|
|
||||||
echo $query . PHP_EOL;
|
|
||||||
die;
|
|
||||||
}
|
|
||||||
PropertyModel::set(PropertyModel::DbVersion, $upgradeVersionMajor . '.' . $upgradeVersionMinor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PropertyModel::set(PropertyModel::DbVersion, $upgradeVersionMajor);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf('%s: no need to execute' . PHP_EOL, $upgradePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
list ($dbVersionMajor, $dbVersionMinor) = getDbVersion();
|
|
||||||
printf('Database version: %d.%d' . PHP_EOL, $dbVersionMajor, $dbVersionMinor);
|
|
||||||
}
|
|
||||||
|
|
10
tests/ITestRunner.php
Normal file
10
tests/ITestRunner.php
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
interface ITestRunner
|
||||||
|
{
|
||||||
|
public function setFilter($filter);
|
||||||
|
public function setTestsPath($testsPath);
|
||||||
|
public function setEnvironmentPrepareAction($callback);
|
||||||
|
public function setEnvironmentCleanAction($callback);
|
||||||
|
public function setTestWrapperAction($callback);
|
||||||
|
public function run();
|
||||||
|
}
|
8
tests/TestResult.php
Normal file
8
tests/TestResult.php
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?php
|
||||||
|
class TestResult
|
||||||
|
{
|
||||||
|
public $duration;
|
||||||
|
public $success;
|
||||||
|
public $exception;
|
||||||
|
public $origin;
|
||||||
|
}
|
200
tests/TestRunner.php
Normal file
200
tests/TestRunner.php
Normal file
|
@ -0,0 +1,200 @@
|
||||||
|
<?php
|
||||||
|
class TestRunner implements ITestRunner
|
||||||
|
{
|
||||||
|
protected $filter = null;
|
||||||
|
protected $testsPath = __DIR__;
|
||||||
|
|
||||||
|
protected $environmentPrepareAction = null;
|
||||||
|
protected $environmentCleanAction = null;
|
||||||
|
protected $testWrapperAction = null;
|
||||||
|
|
||||||
|
public function setFilter($filter)
|
||||||
|
{
|
||||||
|
$this->filter = $filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTestsPath($testsPath)
|
||||||
|
{
|
||||||
|
$this->testsPath = $testsPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEnvironmentPrepareAction($callback)
|
||||||
|
{
|
||||||
|
$this->environmentPrepareAction = $callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEnvironmentCleanAction($callback)
|
||||||
|
{
|
||||||
|
$this->environmentCleanAction = $callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTestWrapperAction($callback)
|
||||||
|
{
|
||||||
|
$this->testWrapperAction = $callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$testFixtures = $this->getTestFixtures($this->filter);
|
||||||
|
$this->runAll($testFixtures);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getTestFixtures($filter)
|
||||||
|
{
|
||||||
|
$testFiles = [];
|
||||||
|
$path = $this->testsPath;
|
||||||
|
if (!$path)
|
||||||
|
$path = __DIR__;
|
||||||
|
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $fileName)
|
||||||
|
{
|
||||||
|
$path = $fileName->getPathname();
|
||||||
|
if (preg_match('/.*Test.php$/', $path))
|
||||||
|
$testFiles []= $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
$testClasses = \Chibi\Util\Reflection::loadClasses($testFiles);
|
||||||
|
|
||||||
|
$classFilter = $filter;
|
||||||
|
$methodFilter = null;
|
||||||
|
if ($filter !== null and strpos($filter, '::') !== false)
|
||||||
|
{
|
||||||
|
list ($classFilter, $methodFilter) = explode('::', $filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($classFilter)
|
||||||
|
$testClasses = array_filter($testClasses, function($className) use ($classFilter)
|
||||||
|
{
|
||||||
|
return stripos($className, $classFilter) !== false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$testFixtures = [];
|
||||||
|
|
||||||
|
foreach ($testClasses as $class)
|
||||||
|
{
|
||||||
|
$reflectionClass = new ReflectionClass($class);
|
||||||
|
if ($reflectionClass->isAbstract())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$testFixture = new StdClass;
|
||||||
|
$testFixture->class = $reflectionClass;
|
||||||
|
$testFixture->methods = [];
|
||||||
|
foreach ($reflectionClass->getMethods() as $method)
|
||||||
|
{
|
||||||
|
if ($methodFilter and stripos($method->name, $methodFilter) === false)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (preg_match('/test/i', $method->name)
|
||||||
|
and $method->isPublic()
|
||||||
|
and $method->getNumberOfParameters() == 0)
|
||||||
|
{
|
||||||
|
$testFixture->methods []= $method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!empty($testFixture->methods))
|
||||||
|
$testFixtures []= $testFixture;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $testFixtures;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function runAll($testFixtures)
|
||||||
|
{
|
||||||
|
$startTime = microtime(true);
|
||||||
|
|
||||||
|
$testNumber = 0;
|
||||||
|
$resultPrinter = function($result) use (&$testNumber)
|
||||||
|
{
|
||||||
|
printf('%3d %-65s ', ++ $testNumber, $result->origin->class . '::' . $result->origin->name);
|
||||||
|
|
||||||
|
if ($result->success)
|
||||||
|
echo 'OK';
|
||||||
|
else
|
||||||
|
echo 'FAIL';
|
||||||
|
|
||||||
|
printf(' [%.03fs]' . PHP_EOL, $result->duration);
|
||||||
|
if ($result->exception)
|
||||||
|
{
|
||||||
|
echo '---' . PHP_EOL;
|
||||||
|
echo $result->exception->getMessage() . PHP_EOL;
|
||||||
|
echo $result->exception->getTraceAsString() . PHP_EOL;
|
||||||
|
echo '---' . PHP_EOL . PHP_EOL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//run all the methods
|
||||||
|
echo 'Starting tests' . PHP_EOL;
|
||||||
|
|
||||||
|
$success = true;
|
||||||
|
foreach ($testFixtures as $className => $testFixture)
|
||||||
|
{
|
||||||
|
$results = $this->runTestFixture($testFixture, $resultPrinter);
|
||||||
|
|
||||||
|
foreach ($results as $result)
|
||||||
|
$success &= $result->success;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf('%3s %-65s %s [%.03fs]' . PHP_EOL,
|
||||||
|
' ',
|
||||||
|
'All tests',
|
||||||
|
$success ? 'OK' : 'FAIL',
|
||||||
|
microtime(true) - $startTime);
|
||||||
|
|
||||||
|
return $success;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function runTestFixture($testFixture, $resultPrinter)
|
||||||
|
{
|
||||||
|
$instance = $testFixture->class->newInstance();
|
||||||
|
|
||||||
|
$instance->setup();
|
||||||
|
$results = [];
|
||||||
|
foreach ($testFixture->methods as $method)
|
||||||
|
{
|
||||||
|
$result = $this->runTest(function() use ($method, $instance)
|
||||||
|
{
|
||||||
|
$method->invoke($instance);
|
||||||
|
});
|
||||||
|
$result->origin = $method;
|
||||||
|
|
||||||
|
if ($resultPrinter !== null)
|
||||||
|
$resultPrinter($result);
|
||||||
|
|
||||||
|
$results []= $result;
|
||||||
|
}
|
||||||
|
$instance->teardown();
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function runTest($callback)
|
||||||
|
{
|
||||||
|
if ($this->environmentPrepareAction !== null)
|
||||||
|
call_user_func($this->environmentPrepareAction);
|
||||||
|
|
||||||
|
$startTime = microtime(true);
|
||||||
|
$result = new TestResult();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if ($this->testWrapperAction !== null)
|
||||||
|
call_user_func($this->testWrapperAction, $callback);
|
||||||
|
else
|
||||||
|
$callback();
|
||||||
|
$result->success = true;
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
$result->exception = $e;
|
||||||
|
$result->success = false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if ($this->environmentCleanAction !== null)
|
||||||
|
call_user_func($this->environmentCleanAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
$endTime = microtime(true);
|
||||||
|
$result->duration = $endTime - $startTime;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@ class TextHelperTest extends AbstractTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testToIntegerOrNulll()
|
public function testToIntegerOrNull()
|
||||||
{
|
{
|
||||||
$this->assert->areEqual(1, TextHelper::toIntegerOrNull(1));
|
$this->assert->areEqual(1, TextHelper::toIntegerOrNull(1));
|
||||||
$this->assert->areEqual(1, TextHelper::toIntegerOrNull('1'));
|
$this->assert->areEqual(1, TextHelper::toIntegerOrNull('1'));
|
||||||
|
|
|
@ -1,68 +1,23 @@
|
||||||
<?php
|
<?php
|
||||||
require_once __DIR__ . '/../src/core.php';
|
require_once __DIR__ . '/../src/core.php';
|
||||||
require_once __DIR__ . '/../src/upgrade.php';
|
|
||||||
\Chibi\Autoloader::registerFileSystem(__DIR__);
|
\Chibi\Autoloader::registerFileSystem(__DIR__);
|
||||||
|
|
||||||
class TestRunner
|
$dbPath = __DIR__ . '/db.sqlite';
|
||||||
|
|
||||||
|
function cleanDatabase()
|
||||||
{
|
{
|
||||||
protected $dbPath;
|
global $dbPath;
|
||||||
|
if (file_exists($dbPath))
|
||||||
|
unlink($dbPath);
|
||||||
|
}
|
||||||
|
|
||||||
public function __construct()
|
function removeTestFolders()
|
||||||
{
|
{
|
||||||
$this->dbPath = __DIR__ . '/db.sqlite';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function run($options)
|
|
||||||
{
|
|
||||||
$cleanDatabase = (isset($options['c']) or isset($options['clean']));
|
|
||||||
|
|
||||||
if (isset($options['f']))
|
|
||||||
$filter = $options['f'];
|
|
||||||
elseif (isset($options['filter']))
|
|
||||||
$filter = $options['filter'];
|
|
||||||
else
|
|
||||||
$filter = null;
|
|
||||||
|
|
||||||
if ($cleanDatabase)
|
|
||||||
$this->cleanDatabase();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$this->resetEnvironment();
|
|
||||||
upgradeDatabase();
|
|
||||||
|
|
||||||
$testFixtures = $this->getTestFixtures($filter);
|
|
||||||
$this->runAll($testFixtures);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
$this->removeTestFolders();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function cleanDatabase()
|
|
||||||
{
|
|
||||||
if (file_exists($this->dbPath))
|
|
||||||
unlink($this->dbPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function resetEnvironment()
|
|
||||||
{
|
|
||||||
$_SESSION = [];
|
|
||||||
prepareConfig(true);
|
|
||||||
getConfig()->main->dbDriver = 'sqlite';
|
|
||||||
getConfig()->main->dbLocation = $this->dbPath;
|
|
||||||
$this->removeTestFolders();
|
|
||||||
prepareEnvironment(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function removeTestFolders()
|
|
||||||
{
|
|
||||||
$folders =
|
$folders =
|
||||||
[
|
[
|
||||||
realpath(getConfig()->main->filesPath),
|
realpath(Core::getConfig()->main->filesPath),
|
||||||
realpath(getConfig()->main->thumbsPath),
|
realpath(Core::getConfig()->main->thumbsPath),
|
||||||
realpath(dirname(getConfig()->main->logsPath)),
|
realpath(dirname(Core::getConfig()->main->logsPath)),
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($folders as $folder)
|
foreach ($folders as $folder)
|
||||||
|
@ -84,164 +39,46 @@ class TestRunner
|
||||||
}
|
}
|
||||||
rmdir($folder);
|
rmdir($folder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getTestFixtures($filter)
|
function resetEnvironment()
|
||||||
{
|
{
|
||||||
$testFiles = [];
|
global $dbPath;
|
||||||
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__)) as $fileName)
|
|
||||||
{
|
|
||||||
$path = $fileName->getPathname();
|
|
||||||
if (preg_match('/.*Test.php$/', $path))
|
|
||||||
$testFiles []= $path;
|
|
||||||
}
|
|
||||||
|
|
||||||
$testClasses = \Chibi\Util\Reflection::loadClasses($testFiles);
|
$_SESSION = [];
|
||||||
|
Core::prepareConfig(true);
|
||||||
|
Core::getConfig()->main->dbDriver = 'sqlite';
|
||||||
|
Core::getConfig()->main->dbLocation = $dbPath;
|
||||||
|
removeTestFolders();
|
||||||
|
Core::prepareEnvironment(true);
|
||||||
|
}
|
||||||
|
|
||||||
$classFilter = $filter;
|
$options = getopt('cf:', ['clean', 'filter:']);
|
||||||
$methodFilter = null;
|
$cleanDatabase = (isset($options['c']) or isset($options['clean']));
|
||||||
if ($filter !== null and strpos($filter, '::') !== false)
|
|
||||||
{
|
|
||||||
list ($classFilter, $methodFilter) = explode('::', $filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($classFilter)
|
if (isset($options['f']))
|
||||||
$testClasses = array_filter($testClasses, function($className) use ($classFilter)
|
$filter = $options['f'];
|
||||||
{
|
elseif (isset($options['filter']))
|
||||||
return stripos($className, $classFilter) !== false;
|
$filter = $options['filter'];
|
||||||
});
|
else
|
||||||
|
$filter = null;
|
||||||
|
|
||||||
$testFixtures = [];
|
resetEnvironment();
|
||||||
|
if ($cleanDatabase)
|
||||||
|
cleanDatabase();
|
||||||
|
resetEnvironment();
|
||||||
|
|
||||||
foreach ($testClasses as $class)
|
Core::upgradeDatabase();
|
||||||
{
|
|
||||||
$reflectionClass = new ReflectionClass($class);
|
|
||||||
if ($reflectionClass->isAbstract())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
$testFixture = new StdClass;
|
$testRunner = new TestRunner;
|
||||||
$testFixture->class = $reflectionClass;
|
$testRunner->setFilter($filter);
|
||||||
$testFixture->methods = [];
|
$testRunner->setEnvironmentPrepareAction(function() { resetEnvironment(); });
|
||||||
foreach ($reflectionClass->getMethods() as $method)
|
$testRunner->setEnvironmentCleanAction(function() { removeTestFolders(); });
|
||||||
{
|
$testRunner->setTestWrapperAction(function($callback)
|
||||||
if ($methodFilter and stripos($method->name, $methodFilter) === false)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (preg_match('/test/i', $method->name)
|
|
||||||
and $method->isPublic()
|
|
||||||
and $method->getNumberOfParameters() == 0)
|
|
||||||
{
|
|
||||||
$testFixture->methods []= $method;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($testFixture->methods))
|
|
||||||
$testFixtures []= $testFixture;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $testFixtures;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function runAll($testFixtures)
|
|
||||||
{
|
|
||||||
$startTime = microtime(true);
|
|
||||||
|
|
||||||
$testNumber = 0;
|
|
||||||
$resultPrinter = function($result) use (&$testNumber)
|
|
||||||
{
|
|
||||||
printf('%3d %-65s ', ++ $testNumber, $result->origin->class . '::' . $result->origin->name);
|
|
||||||
|
|
||||||
if ($result->success)
|
|
||||||
echo 'OK';
|
|
||||||
else
|
|
||||||
echo 'FAIL';
|
|
||||||
|
|
||||||
printf(' [%.03fs]' . PHP_EOL, $result->duration);
|
|
||||||
if ($result->exception)
|
|
||||||
{
|
|
||||||
echo '---' . PHP_EOL;
|
|
||||||
echo $result->exception->getMessage() . PHP_EOL;
|
|
||||||
echo $result->exception->getTraceAsString() . PHP_EOL;
|
|
||||||
echo '---' . PHP_EOL . PHP_EOL;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//run all the methods
|
|
||||||
echo 'Starting tests' . PHP_EOL;
|
|
||||||
|
|
||||||
$success = true;
|
|
||||||
foreach ($testFixtures as $className => $testFixture)
|
|
||||||
{
|
|
||||||
$results = $this->runTestFixture($testFixture, $resultPrinter);
|
|
||||||
|
|
||||||
foreach ($results as $result)
|
|
||||||
$success &= $result->success;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf('%3s %-65s %s [%.03fs]' . PHP_EOL,
|
|
||||||
' ',
|
|
||||||
'All tests',
|
|
||||||
$success ? 'OK' : 'FAIL',
|
|
||||||
microtime(true) - $startTime);
|
|
||||||
|
|
||||||
return $success;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function runTestFixture($testFixture, $resultPrinter)
|
|
||||||
{
|
|
||||||
$instance = $testFixture->class->newInstance();
|
|
||||||
|
|
||||||
$instance->setup();
|
|
||||||
$results = [];
|
|
||||||
foreach ($testFixture->methods as $method)
|
|
||||||
{
|
|
||||||
$result = $this->runTest(function() use ($method, $instance)
|
|
||||||
{
|
|
||||||
$method->invoke($instance);
|
|
||||||
});
|
|
||||||
$result->origin = $method;
|
|
||||||
|
|
||||||
if ($resultPrinter !== null)
|
|
||||||
$resultPrinter($result);
|
|
||||||
|
|
||||||
$results []= $result;
|
|
||||||
}
|
|
||||||
$instance->teardown();
|
|
||||||
return $results;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function runTest($callback)
|
|
||||||
{
|
|
||||||
$this->resetEnvironment();
|
|
||||||
|
|
||||||
$startTime = microtime(true);
|
|
||||||
$result = new TestResult();
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
\Chibi\Database::rollback(function() use ($callback)
|
\Chibi\Database::rollback(function() use ($callback)
|
||||||
{
|
{
|
||||||
$callback();
|
$callback();
|
||||||
});
|
});
|
||||||
$result->success = true;
|
});
|
||||||
}
|
$testRunner->run($filter);
|
||||||
catch (Exception $e)
|
|
||||||
{
|
|
||||||
$result->exception = $e;
|
|
||||||
$result->success = false;
|
|
||||||
}
|
|
||||||
$endTime = microtime(true);
|
|
||||||
$result->duration = $endTime - $startTime;
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestResult
|
|
||||||
{
|
|
||||||
public $duration;
|
|
||||||
public $success;
|
|
||||||
public $exception;
|
|
||||||
public $origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
$options = getopt('cf:', ['clean', 'filter:']);
|
|
||||||
(new TestRunner)->run($options);
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
<?php
|
<?php
|
||||||
require_once 'src/core.php';
|
require_once 'src/core.php';
|
||||||
require_once 'src/upgrade.php';
|
Core::upgradeDatabase();
|
||||||
upgradeDatabase();
|
|
||||||
|
|
Loading…
Reference in a new issue