-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Configurable cached fixtures directory #118
Comments
Thanks for the detailed issue. The support of paratest was removed to ease the maintenance of this bundle in #56, but we can restore it. So we have to be able to:
Could you please show the code that work for you today? |
Thanks for looking into this. We use the ConnectionFactory from the old times of the bundle (even has old reference to LiipFunctionalTestBundle): use Doctrine\Bundle\DoctrineBundle\ConnectionFactory as BaseConnectionFactory;
use Doctrine\Common\EventManager;
use Doctrine\DBAL\Configuration;
/**
* Creates a connection taking the db name from the env with
* a unique number defined by current process ID.
*
* @link https://github.com/liip/LiipFunctionalTestBundle/blob/master/Factory/ConnectionFactory.php idea borrowed here
*/
class DBALConnectionFactory extends BaseConnectionFactory
{
/**
* Create a connection by name.
*
* @param array $params
* @param Configuration $config
* @param EventManager $eventManager
* @param array $mappingTypes
*
* @return \Doctrine\DBAL\Connection
*/
public function createConnection(array $params, Configuration $config = null, EventManager $eventManager = null, array $mappingTypes = array())
{
$parallelPrefix = getenv('TEST_TOKEN');
if ($params['driver'] === 'pdo_sqlite') {
$params['path'] = str_replace('__DBNAME__', $parallelPrefix, $params['path']);
} else {
$params['dbname'] = str_replace('__DBNAME__', $parallelPrefix, $params['dbname']);
}
return parent::createConnection($params, $config, $eventManager, $mappingTypes);
}
} And the one we use for sqlite fixtures replacement use Doctrine\Common\DataFixtures\Executor\AbstractExecutor;
use Doctrine\DBAL\Connection;
use Doctrine\ORM\EntityManager;
/**
* @author Aleksey Tupichenkov <[email protected]>
*/
final class SqliteDatabaseBackup extends AbstractDatabaseBackup implements DatabaseBackupInterface
{
public function getBackupFilePath(): string
{
$token = getenv('TEST_TOKEN') ?: 'default';
return $this->container->getParameter('kernel.cache_dir').'/test_sqlite_'. $token . md5(serialize($this->metadatas).serialize($this->classNames)).'.db';
}
private function getDatabaseName(Connection $connection): string
{
$params = $connection->getParams();
if (isset($params['master'])) {
$params = $params['master'];
}
$name = $params['path'] ?? ($params['dbname'] ?? false);
if (!$name) {
throw new \InvalidArgumentException("Connection does not contain a 'path' or 'dbname' parameter and cannot be dropped.");
}
return $name;
}
public function isBackupActual(): bool
{
$backupDBFileName = $this->getBackupFilePath();
$backupReferenceFileName = $backupDBFileName.'.ser';
return file_exists($backupDBFileName) && file_exists($backupReferenceFileName) && $this->isBackupUpToDate($backupDBFileName);
}
public function backup(AbstractExecutor $executor): void
{
/** @var EntityManager $em */
$em = $executor->getReferenceRepository()->getManager();
$connection = $em->getConnection();
$executor->getReferenceRepository()->save($this->getBackupFilePath());
copy($this->getDatabaseName($connection), $this->getBackupFilePath());
}
public function restore(AbstractExecutor $executor, array $excludedTables = []): void
{
/** @var EntityManager $em */
$em = $executor->getReferenceRepository()->getManager();
$connection = $em->getConnection();
copy($this->getBackupFilePath(), $this->getDatabaseName($connection));
$executor->getReferenceRepository()->load($this->getBackupFilePath());
}
} Had to copy-paste class because it's final in the bundle. Need to note that we're using latest 1.x version due to older symfony dependencies. |
This bundle now seems to support paratest out of the box? Except I'm still getting this issue with caching the sqlite database. Would it be worth me submitting a PR for this? public function getBackupFilePath(): string
{
+ $token = \getenv('TEST_TOKEN') ?: 'default';
+ return $this->container->getParameter('kernel.cache_dir').'/test_sqlite_'.$token.\md5(\serialize($this->metadatas).\serialize($this->classNames)).'.db';
- return $this->container->getParameter('kernel.cache_dir').'/test_sqlite_'.md5(serialize($this->metadatas).serialize($this->classNames)).'.db';
}
|
Is your feature request related to a problem? Please describe.
We've switched from custom implementation to this library to leverage fixtures caching (thanks for extraction from
liip/LiipFunctionalTestBundle
!). Also we use paratest to speed up our sqlite tests execution. To guarantee that the used database is different for each thread, we useTEST_TOKEN
provided by paratest and connection factory similar to the one provided in https://github.com/liip/LiipTestFixturesBundle/blob/2.x/src/Factory/ConnectionFactory.php (btw it looks broken now asgetDbNameFromEnv
is not used)Unfortunately, we still end up in concurrency problems but in fixtures backup usage, being it loading or restoring from fixtures. In our custom implementation we solved it with similar to connection factory - use different folders for different threads. It's possible to maintain this behavior by overwriting service definition of
\Liip\TestFixturesBundle\Services\DatabaseBackup\SqliteDatabaseBackup
but will appreciate if configurability of cache folder makes it to upstreamDescribe the solution you'd like
\Liip\TestFixturesBundle\Services\DatabaseBackup\SqliteDatabaseBackup::getBackupFilePath
cache folder (for other providers it's the same) should be configurable and instead of using$this->container->getParameter('kernel.cache_dir')
allow configuration to come from bundle configuration.For backwards-compatibility this parameter can be
%kernel.cache_dir%
by default.Describe alternatives you've considered
Alternatives are to keep overwritten service definition on our side, but it's prone to future breaking changes.
Additional context
I've tried to add more configuration to
liip_test_fixtures.cache_db
but it accepts only service id, so I don't see clear non-breaking change here. Looking for alternatives and up to implement it f it satisfies both maintainers and my use case.The text was updated successfully, but these errors were encountered: