Ambiente de testeo
This commit is contained in:
@ -2,7 +2,7 @@
|
|||||||
<phpunit
|
<phpunit
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.4/phpunit.xsd"
|
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.4/phpunit.xsd"
|
||||||
bootstrap="vendor/autoload.php"
|
bootstrap="test.bootstrap.php"
|
||||||
cacheDirectory="/code/cache/tests"
|
cacheDirectory="/code/cache/tests"
|
||||||
executionOrder="depends,defects"
|
executionOrder="depends,defects"
|
||||||
requireCoverageMetadata="false"
|
requireCoverageMetadata="false"
|
||||||
@ -34,10 +34,10 @@
|
|||||||
<php outputFile="/code/public/coverage/coverage.php"/>
|
<php outputFile="/code/public/coverage/coverage.php"/>
|
||||||
</report>
|
</report>
|
||||||
</coverage>
|
</coverage>
|
||||||
<!--<logging>
|
<logging>
|
||||||
<junit outputFile="/code/cache/tests/junit.xml"/>
|
<junit outputFile="/code/cache/tests/junit.xml"/>
|
||||||
<teamcity outputFile="/code/cache/tests/teamcity.txt"/>
|
<teamcity outputFile="/code/cache/tests/teamcity.txt"/>
|
||||||
<testdoxHtml outputFile="/code/cache/tests/testdox.html"/>
|
<testdoxHtml outputFile="/code/cache/tests/testdox.html"/>
|
||||||
<testdoxText outputFile="/code/cache/tests/testdox.txt"/>
|
<testdoxText outputFile="/code/cache/tests/testdox.txt"/>
|
||||||
</logging>-->
|
</logging>
|
||||||
</phpunit>
|
</phpunit>
|
||||||
|
@ -5,42 +5,149 @@ require_once implode(DIRECTORY_SEPARATOR, [
|
|||||||
'autoload.php'
|
'autoload.php'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function setupDatabase(string $schemaFilename): void {
|
class Benchmark
|
||||||
printf("Loading database schema from %s", $schemaFilename);
|
{
|
||||||
$start = microtime(true);
|
protected static array $queue = [];
|
||||||
|
public static function print(): void
|
||||||
$dsn = "mysql:host={$_ENV['DB_HOST']};dbname={$_ENV['DB_DATABASE']}";
|
{
|
||||||
$pdo = new PDO($dsn, $_ENV['DB_USER'], $_ENV['DB_PASSWORD']);
|
if (empty(self::$queue)) {
|
||||||
|
return;
|
||||||
$sql = file_get_contents($schemaFilename);
|
}
|
||||||
$pdo->exec($sql);
|
echo implode(PHP_EOL, self::$queue), PHP_EOL;
|
||||||
|
self::$queue = [];
|
||||||
$end = microtime(true);
|
|
||||||
printf(" in %.2f seconds\n", $end - $start);
|
|
||||||
}
|
|
||||||
function truncateTables(): void {
|
|
||||||
printf("Truncating tables");
|
|
||||||
$start = microtime(true);
|
|
||||||
|
|
||||||
$dsn = "mysql:host={$_ENV['DB_HOST']};dbname={$_ENV['DB_DATABASE']}";
|
|
||||||
$pdo = new PDO($dsn, $_ENV['DB_USER'], $_ENV['DB_PASSWORD']);
|
|
||||||
|
|
||||||
$pdo->exec("SET FOREIGN_KEY_CHECKS=0");
|
|
||||||
$statement = $pdo->query('SHOW TABLES');
|
|
||||||
$tables = array_map(function(array $row) {
|
|
||||||
return $row["Tables_in_{$_ENV['DB_DATABASE']}"];
|
|
||||||
}, $statement->fetchAll(PDO::FETCH_ASSOC));
|
|
||||||
|
|
||||||
foreach ($tables as $table) {
|
|
||||||
$pdo->exec("TRUNCATE TABLE `$table`");
|
|
||||||
}
|
}
|
||||||
$pdo->exec("SET FOREIGN_KEY_CHECKS=1");
|
|
||||||
|
|
||||||
$end = microtime(true);
|
public static function execute(callable $callback, ?array $args = null, ?string $description = null): mixed
|
||||||
printf(" in %.2f seconds\n", $end - $start);
|
{
|
||||||
|
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]',
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$schemaFilename = implode(DIRECTORY_SEPARATOR, [__DIR__, 'resources', 'database', 'schema.sql']);
|
class TestBootstrap
|
||||||
setupDatabase($schemaFilename);
|
{
|
||||||
register_shutdown_function(function() {
|
public function __construct(protected array $configuration) {}
|
||||||
truncateTables();
|
|
||||||
|
public function run(): void
|
||||||
|
{
|
||||||
|
if (Benchmark::execute([$this, 'isMigrated'])) {
|
||||||
|
Benchmark::execute([$this, 'resetDatabase']);
|
||||||
|
}
|
||||||
|
Benchmark::execute([$this, 'migrate']);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
public function migrate(): void
|
||||||
|
{
|
||||||
|
$cmd = "{$this->baseCommand} migrate -e testing";
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$bootstrap = new TestBootstrap($_ENV);
|
||||||
|
Benchmark::execute([$bootstrap, 'run']);
|
||||||
|
Benchmark::print();
|
||||||
|
|
||||||
|
register_shutdown_function(function() use ($bootstrap) {
|
||||||
|
Benchmark::execute([$bootstrap, 'truncateTables']);
|
||||||
|
Benchmark::print();
|
||||||
});
|
});
|
||||||
|
@ -84,20 +84,6 @@ services:
|
|||||||
- ${CLI_PATH:-.}:/code
|
- ${CLI_PATH:-.}:/code
|
||||||
- ./logs/cli:/logs
|
- ./logs/cli:/logs
|
||||||
|
|
||||||
testing:
|
|
||||||
profiles:
|
|
||||||
- testing
|
|
||||||
container_name: incoviba_tests
|
|
||||||
build: .
|
|
||||||
restart: unless-stopped
|
|
||||||
env_file:
|
|
||||||
- ${APP_PATH:-.}/.env
|
|
||||||
- ./.key.env
|
|
||||||
volumes:
|
|
||||||
- ${APP_PATH:-.}/:/code
|
|
||||||
- ./logs/test:/logs
|
|
||||||
command: [ '/code/bin/phpunit-watcher', 'watch' ]
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
dbdata: {}
|
dbdata: {}
|
||||||
incoviba_redis: {}
|
incoviba_redis: {}
|
||||||
|
@ -2,34 +2,32 @@ services:
|
|||||||
testing:
|
testing:
|
||||||
profiles:
|
profiles:
|
||||||
- testing
|
- testing
|
||||||
container_name: incoviba_tests
|
|
||||||
build: .
|
build: .
|
||||||
restart: unless-stopped
|
container_name: incoviba_tests
|
||||||
env_file:
|
env_file:
|
||||||
- ${APP_PATH:-.}/.test.env
|
- ${APP_PATH:-.}/.test.env
|
||||||
- ./.key.env
|
- ./.key.env
|
||||||
volumes:
|
volumes:
|
||||||
- ${APP_PATH:-.}/:/code
|
- ${APP_PATH:-.}/:/code
|
||||||
- ./logs/test:/logs
|
|
||||||
command: [ '/code/bin/phpunit-watcher', 'watch' ]
|
command: [ '/code/bin/phpunit-watcher', 'watch' ]
|
||||||
|
networks:
|
||||||
|
- testing
|
||||||
depends_on:
|
depends_on:
|
||||||
- test-db
|
- test-db
|
||||||
|
|
||||||
test-db:
|
test-db:
|
||||||
profiles:
|
profiles:
|
||||||
- testing
|
- testing
|
||||||
image: mysql:5.7
|
image: mariadb:latest
|
||||||
container_name: incoviba_test_db
|
container_name: incoviba_test_db
|
||||||
restart: unless-stopped
|
|
||||||
env_file: ${APP_PATH:-.}/.test.db.env
|
env_file: ${APP_PATH:-.}/.test.db.env
|
||||||
volumes:
|
volumes:
|
||||||
- test-db:/var/lib/mysql
|
- test-db:/var/lib/mysql
|
||||||
networks:
|
networks:
|
||||||
- default
|
- testing
|
||||||
- adminer_network
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
test-db: {}
|
test-db: {}
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
adminer_network: {}
|
testing: {}
|
||||||
|
Reference in New Issue
Block a user