2014-05-04 21:23:12 +02:00
|
|
|
<?php
|
2014-05-06 11:18:04 +02:00
|
|
|
require_once __DIR__ . '/../src/core.php';
|
|
|
|
require_once __DIR__ . '/../src/upgrade.php';
|
|
|
|
\Chibi\Autoloader::registerFileSystem(__DIR__);
|
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
class TestRunner
|
|
|
|
{
|
|
|
|
protected $dbPath;
|
2014-05-05 17:13:26 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
public function __construct()
|
|
|
|
{
|
|
|
|
$this->dbPath = __DIR__ . '/db.sqlite';
|
|
|
|
}
|
2014-05-04 21:23:12 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
public function run($options)
|
|
|
|
{
|
|
|
|
$cleanDatabase = (isset($options['c']) or isset($options['clean']));
|
2014-05-06 12:01:29 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
if (isset($options['f']))
|
|
|
|
$filter = $options['f'];
|
|
|
|
elseif (isset($options['filter']))
|
|
|
|
$filter = $options['filter'];
|
|
|
|
else
|
|
|
|
$filter = null;
|
2014-05-06 12:01:29 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
if ($cleanDatabase)
|
|
|
|
$this->cleanDatabase();
|
2014-05-04 21:23:12 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
try
|
|
|
|
{
|
|
|
|
$this->resetEnvironment();
|
|
|
|
upgradeDatabase();
|
2014-05-06 12:01:29 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
$testFixtures = $this->getTestFixtures($filter);
|
|
|
|
$this->runAll($testFixtures);
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
$this->removeTestFolders();
|
|
|
|
}
|
|
|
|
}
|
2014-05-04 21:23:12 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
protected function cleanDatabase()
|
2014-05-06 15:09:06 +02:00
|
|
|
{
|
2014-05-06 18:09:23 +02:00
|
|
|
if (file_exists($this->dbPath))
|
|
|
|
unlink($this->dbPath);
|
|
|
|
}
|
2014-05-06 15:09:06 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
protected function resetEnvironment()
|
|
|
|
{
|
2014-05-13 00:02:25 +02:00
|
|
|
$_SESSION = [];
|
2014-05-06 18:09:23 +02:00
|
|
|
prepareConfig(true);
|
|
|
|
getConfig()->main->dbDriver = 'sqlite';
|
|
|
|
getConfig()->main->dbLocation = $this->dbPath;
|
|
|
|
$this->removeTestFolders();
|
|
|
|
prepareEnvironment(true);
|
|
|
|
}
|
2014-05-06 15:09:06 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
protected function removeTestFolders()
|
|
|
|
{
|
|
|
|
$folders =
|
|
|
|
[
|
|
|
|
realpath(getConfig()->main->filesPath),
|
|
|
|
realpath(getConfig()->main->thumbsPath),
|
|
|
|
realpath(dirname(getConfig()->main->logsPath)),
|
|
|
|
];
|
|
|
|
|
|
|
|
foreach ($folders as $folder)
|
2014-05-06 15:09:06 +02:00
|
|
|
{
|
2014-05-06 18:09:23 +02:00
|
|
|
if (!file_exists($folder))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
$it = new RecursiveIteratorIterator(
|
|
|
|
new RecursiveDirectoryIterator(
|
|
|
|
$folder,
|
|
|
|
FilesystemIterator::SKIP_DOTS),
|
|
|
|
RecursiveIteratorIterator::CHILD_FIRST);
|
|
|
|
|
|
|
|
foreach ($it as $path)
|
|
|
|
{
|
|
|
|
$path->isFile()
|
|
|
|
? unlink($path->getPathname())
|
|
|
|
: rmdir($path->getPathname());
|
|
|
|
}
|
|
|
|
rmdir($folder);
|
2014-05-06 15:09:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
protected function getTestFixtures($filter)
|
2014-05-06 11:18:04 +02:00
|
|
|
{
|
2014-05-06 18:09:23 +02:00
|
|
|
$testFiles = [];
|
|
|
|
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__)) as $fileName)
|
|
|
|
{
|
|
|
|
$path = $fileName->getPathname();
|
|
|
|
if (preg_match('/.*Test.php$/', $path))
|
|
|
|
$testFiles []= $path;
|
|
|
|
}
|
2014-05-06 11:18:04 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
$testClasses = \Chibi\Util\Reflection::loadClasses($testFiles);
|
2014-05-05 17:13:26 +02:00
|
|
|
|
2014-05-14 19:06:27 +02:00
|
|
|
$classFilter = $filter;
|
|
|
|
$methodFilter = null;
|
|
|
|
if ($filter !== null and strpos($filter, '::') !== false)
|
2014-05-05 17:13:26 +02:00
|
|
|
{
|
2014-05-14 19:06:27 +02:00
|
|
|
list ($classFilter, $methodFilter) = explode('::', $filter);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($classFilter)
|
|
|
|
$testClasses = array_filter($testClasses, function($className) use ($classFilter)
|
2014-05-06 18:09:23 +02:00
|
|
|
{
|
2014-05-14 19:06:27 +02:00
|
|
|
return stripos($className, $classFilter) !== false;
|
2014-05-06 18:09:23 +02:00
|
|
|
});
|
2014-05-05 17:13:26 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
$testFixtures = [];
|
2014-05-04 21:23:12 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
foreach ($testClasses as $class)
|
2014-05-04 21:23:12 +02:00
|
|
|
{
|
2014-05-06 18:09:23 +02:00
|
|
|
$reflectionClass = new ReflectionClass($class);
|
|
|
|
if ($reflectionClass->isAbstract())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
$testFixture = new StdClass;
|
|
|
|
$testFixture->class = $reflectionClass;
|
|
|
|
$testFixture->methods = [];
|
|
|
|
foreach ($reflectionClass->getMethods() as $method)
|
2014-05-04 21:23:12 +02:00
|
|
|
{
|
2014-05-14 19:06:27 +02:00
|
|
|
if ($methodFilter and stripos($method->name, $methodFilter) === false)
|
|
|
|
continue;
|
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
if (preg_match('/test/i', $method->name)
|
|
|
|
and $method->isPublic()
|
|
|
|
and $method->getNumberOfParameters() == 0)
|
|
|
|
{
|
|
|
|
$testFixture->methods []= $method;
|
|
|
|
}
|
2014-05-04 21:23:12 +02:00
|
|
|
}
|
2014-05-14 19:06:27 +02:00
|
|
|
|
|
|
|
if (!empty($testFixture->methods))
|
|
|
|
$testFixtures []= $testFixture;
|
2014-05-04 21:23:12 +02:00
|
|
|
}
|
2014-05-06 18:09:23 +02:00
|
|
|
|
|
|
|
return $testFixtures;
|
2014-05-04 21:23:12 +02:00
|
|
|
}
|
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
protected function runAll($testFixtures)
|
|
|
|
{
|
|
|
|
$startTime = microtime(true);
|
2014-05-04 21:23:12 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
$testNumber = 0;
|
|
|
|
$resultPrinter = function($result) use (&$testNumber)
|
|
|
|
{
|
|
|
|
printf('%3d %-65s ', ++ $testNumber, $result->origin->class . '::' . $result->origin->name);
|
2014-05-04 21:23:12 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
if ($result->success)
|
|
|
|
echo 'OK';
|
|
|
|
else
|
|
|
|
echo 'FAIL';
|
2014-05-04 21:23:12 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
};
|
2014-05-04 21:23:12 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
//run all the methods
|
|
|
|
echo 'Starting tests' . PHP_EOL;
|
2014-05-04 21:23:12 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
$success = true;
|
|
|
|
foreach ($testFixtures as $className => $testFixture)
|
|
|
|
{
|
|
|
|
$results = $this->runTestFixture($testFixture, $resultPrinter);
|
2014-05-04 21:23:12 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
foreach ($results as $result)
|
|
|
|
$success &= $result->success;
|
|
|
|
}
|
2014-05-04 21:23:12 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
printf('%3s %-65s %s [%.03fs]' . PHP_EOL,
|
|
|
|
' ',
|
|
|
|
'All tests',
|
|
|
|
$success ? 'OK' : 'FAIL',
|
|
|
|
microtime(true) - $startTime);
|
2014-05-04 21:23:12 +02:00
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
return $success;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function runTestFixture($testFixture, $resultPrinter)
|
|
|
|
{
|
|
|
|
$instance = $testFixture->class->newInstance();
|
|
|
|
|
|
|
|
$instance->setup();
|
|
|
|
$results = [];
|
|
|
|
foreach ($testFixture->methods as $method)
|
2014-05-04 21:23:12 +02:00
|
|
|
{
|
2014-05-06 18:09:23 +02:00
|
|
|
$result = $this->runTest(function() use ($method, $instance)
|
2014-05-04 21:23:12 +02:00
|
|
|
{
|
|
|
|
$method->invoke($instance);
|
|
|
|
});
|
2014-05-06 18:09:23 +02:00
|
|
|
$result->origin = $method;
|
|
|
|
|
|
|
|
if ($resultPrinter !== null)
|
|
|
|
$resultPrinter($result);
|
|
|
|
|
|
|
|
$results []= $result;
|
2014-05-04 21:23:12 +02:00
|
|
|
}
|
2014-05-06 18:09:23 +02:00
|
|
|
$instance->teardown();
|
|
|
|
return $results;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function runTest($callback)
|
|
|
|
{
|
|
|
|
$this->resetEnvironment();
|
|
|
|
|
|
|
|
$startTime = microtime(true);
|
|
|
|
$result = new TestResult();
|
|
|
|
try
|
2014-05-04 21:23:12 +02:00
|
|
|
{
|
2014-05-06 18:09:23 +02:00
|
|
|
\Chibi\Database::rollback(function() use ($callback)
|
|
|
|
{
|
|
|
|
$callback();
|
|
|
|
});
|
|
|
|
$result->success = true;
|
2014-05-04 21:23:12 +02:00
|
|
|
}
|
2014-05-06 18:09:23 +02:00
|
|
|
catch (Exception $e)
|
2014-05-04 21:23:12 +02:00
|
|
|
{
|
2014-05-06 18:09:23 +02:00
|
|
|
$result->exception = $e;
|
|
|
|
$result->success = false;
|
2014-05-04 21:23:12 +02:00
|
|
|
}
|
2014-05-06 18:09:23 +02:00
|
|
|
$endTime = microtime(true);
|
|
|
|
$result->duration = $endTime - $startTime;
|
|
|
|
return $result;
|
2014-05-04 21:23:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-06 18:09:23 +02:00
|
|
|
class TestResult
|
2014-05-04 21:23:12 +02:00
|
|
|
{
|
2014-05-06 18:09:23 +02:00
|
|
|
public $duration;
|
|
|
|
public $success;
|
|
|
|
public $exception;
|
|
|
|
public $origin;
|
2014-05-04 21:23:12 +02:00
|
|
|
}
|
2014-05-06 18:09:23 +02:00
|
|
|
|
|
|
|
$options = getopt('cf:', ['clean', 'filter:']);
|
|
|
|
(new TestRunner)->run($options);
|