Files
oficial/app/test.bootstrap.php
aldarien 307f2ac7d7 feature/cierres (#25)
Varios cambios

Co-authored-by: Juan Pablo Vial <jpvialb@incoviba.cl>
Reviewed-on: #25
2025-07-22 13:18:00 +00:00

188 lines
6.2 KiB
PHP

<?php
require_once implode(DIRECTORY_SEPARATOR, [
__DIR__,
'vendor',
'autoload.php'
]);
class Benchmark
{
protected static array $queue = [];
public static function print(): void
{
if (empty(self::$queue)) {
return;
}
echo implode(PHP_EOL, self::$queue), PHP_EOL;
self::$queue = [];
}
public static function execute(callable $callback, ?array $args = null, ?string $description = null): mixed
{
if (null === $description) {
$description = self::getCallableName($callback);
}
$i = count(self::$queue);
self::$queue[$i] = "Executing $description";
$start = microtime(true);
if (null === $args) {
$result = call_user_func($callback);
} else {
$result = call_user_func_array($callback, $args);
}
$end = microtime(true);
self::$queue[$i] .= sprintf(" in %.2f seconds", $end - $start);
return $result;
}
public static function getCallableName(callable $callable): string
{
return match (true) {
is_string($callable) && strpos($callable, '::') => '[static] ' . $callable,
is_string($callable) => '[function] ' . $callable,
is_array($callable) && is_object($callable[0]) => '[method] ' . get_class($callable[0]) . '->' . $callable[1],
is_array($callable) => '[static] ' . $callable[0] . '::' . $callable[1],
$callable instanceof Closure => '[closure]',
is_object($callable) => '[invokable] ' . get_class($callable),
default => '[unknown]',
};
}
}
class TestBootstrap
{
public function __construct(protected array $configuration) {}
public function run(bool $debug = false): void
{
if (!Benchmark::execute([$this, 'isMigrated'])) {
Benchmark::execute([$this, 'migrate']);
}
$output = Benchmark::execute([$this, 'seedTables']);
if ($debug) {
var_dump($output);
}
}
protected string $baseCommand = "bin/phinx";
public function isMigrated(): bool
{
$cmd = "{$this->baseCommand} status -e testing -f json --no-info";
$output = shell_exec($cmd);
$status = json_decode($output, true);
return $status['missing_count'] === 0 and $status['pending_count'] === 0;
}
public function migrate(): false|null|string
{
$cmd = "{$this->baseCommand} migrate -e testing";
return shell_exec($cmd);
}
public function resetDatabase(): void
{
$tables = $this->getTables();
if ($this->connect()->beginTransaction()) {
try {
$this->connect()->query("SET FOREIGN_KEY_CHECKS=0;");
foreach ($tables as $table) {
$this->connect()->query("DROP TABLE IF EXISTS `{$table}`");
}
$this->connect()->query("SET FOREIGN_KEY_CHECKS=1;");
if ($this->connect()->inTransaction()) {
$this->connect()->commit();
}
} catch (PDOException $exception) {
if ($this->connect()->inTransaction()) {
$this->connect()->rollBack();
}
throw $exception;
}
}
}
public function truncateTables(): void
{
$tables = $this->getTables();
if ($this->connect()->beginTransaction()) {
try {
$this->connect()->query("SET FOREIGN_KEY_CHECKS=0;");
foreach ($tables as $table) {
$this->connect()->query("TRUNCATE TABLE `{$table}`");
}
$this->connect()->query("SET FOREIGN_KEY_CHECKS=1;");
if ($this->connect()->inTransaction()) {
$this->connect()->commit();
}
} catch (PDOException $exception) {
if ($this->connect()->inTransaction()) {
$this->connect()->rollBack();
}
throw $exception;
}
}
}
public function seedTables(): false|null|string
{
$cmd = "{$this->baseCommand} seed:run -e testing";
$output = shell_exec($cmd);
$testSeeder = new Tests\Extension\TestSeeder($this->connect());
$testSeeder->run();
return $output;
}
protected PDO $connection;
protected function connect(): PDO
{
if (!isset($this->connection)) {
$dsn = "mysql:host={$this->configuration['DB_HOST']};dbname={$this->configuration['DB_DATABASE']}";
$this->connection = new PDO(
$dsn,
$this->configuration['DB_USER'],
$this->configuration['DB_PASSWORD']
);
}
return $this->connection;
}
protected array $tables;
protected function getTables(): array
{
if (!isset($this->tables)) {
$this->tables = $this->connect()->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
}
return $this->tables;
}
}
spl_autoload_register(function($className) {
$baseTestPath = __DIR__ . "/tests";
$namespaceMap = [
"Tests\\Extension\\" => "{$baseTestPath}/extension",
"Tests\\Integration\\" => "{$baseTestPath}/integration",
"Tests\\Unit\\" => "{$baseTestPath}/unit/src",
"Tests\\Performance\\" => "{$baseTestPath}/performance",
];
foreach ($namespaceMap as $namespace => $path) {
if (str_starts_with($className, $namespace)) {
require str_replace([$namespace, '\\'], ["{$path}/", DIRECTORY_SEPARATOR], $className) . ".php";
return;
}
}
});
$bootstrap = new TestBootstrap($_ENV);
$resetDatabase = (array_key_exists('RESET_DATABASE', $_ENV) and $_ENV['RESET_DATABASE'] === 'true') ?? false;
$debug = (array_key_exists('DEBUG', $_ENV) and $_ENV['DEBUG'] === 'true') ?? false;
Benchmark::execute([$bootstrap, 'run'], ['debug' => $debug]);
Benchmark::print();
register_shutdown_function(function() use ($bootstrap, $resetDatabase) {
$method = 'truncateTables';
if ($resetDatabase) {
$method = 'resetDatabase';
}
Benchmark::execute([$bootstrap, $method]);
Benchmark::print();
});