如何测试 Doctrine Migrations?
How to test Doctrine Migrations?
我正在开发一个项目,该项目在开发环境中没有生产数据库的副本。
有时我们会遇到数据库迁移问题 - 它们传递开发数据库但在 production/testing 中失败。
这通常是因为开发环境数据是从使用最新实体的装置加载的 - 正确填充所有表格。
是否有任何简单的方法来确保 Doctrine Migration(s) 将在生产中通过?
您是否 have/know 有任何方法可以编写自动测试以确保在不下载 production/testing 数据库和 运行 手动迁移的情况下正确迁移数据?
我想避免将 production/testing 数据库下载到开发机器,这样我就可以检查迁移,因为该数据库包含私有数据并且它可能非常大。
我已经为 Doctrine Migrations 想出了简单的 "smoke tests"。
我有 PHPUnit 测试执行以下步骤:
- 跌落测试数据库
- 创建测试数据库
- 加载迁移(创建模式)
- 加载夹具(模拟生产数据)
- 迁移到一些旧版本
- 迁移回最新版本
这样我可以测试我们最近遇到的主要问题。
可以在我的博客上找到 PHPUnit 测试示例:http://damiansromek.pl/2015/09/29/how-to-test-doctrine-migrations/
首先,您需要在迁移前的状态下创建示例数据库转储。对于 MySQL 使用 mysqldump。对于 postgres pg_dump,例如:
mysqldump -u root -p mydatabase > dump-2018-02-20.sql
pg_dump -Upostgres --inserts --encoding utf8 -f dump-2018-02-20.sql mydatabase
然后为所有迁移测试创建一个摘要 class(我假设您已经在 config_test.yml
中为集成测试配置了一个单独的数据库):
abstract class DatabaseMigrationTestCase extends WebTestCase {
/** @var ResettableContainerInterface */
protected $container;
/** @var Application */
private $application;
protected function setUp() {
$this->container = self::createClient()->getContainer();
$kernel = $this->container->get('kernel');
$this->application = new Application($kernel);
$this->application->setAutoExit(false);
$this->application->setCatchExceptions(false);
$em = $this->container->get(EntityManagerInterface::class);
$this->executeCommand('doctrine:schema:drop --force');
$em->getConnection()->exec('DROP TABLE IF EXISTS public.migration_versions');
}
protected function loadDump(string $name) {
$em = $this->container->get(EntityManagerInterface::class);
$em->getConnection()->exec(file_get_contents(__DIR__ . '/dumps/dump-' . $name . '.sql'));
}
protected function executeCommand(string $command): string {
$input = new StringInput("$command --env=test");
$output = new BufferedOutput();
$input->setInteractive(false);
$returnCode = $this->application->run($input, $output);
if ($returnCode != 0) {
throw new \RuntimeException('Failed to execute command. ' . $output->fetch());
}
return $output->fetch();
}
protected function migrate(string $toVersion = '') {
$this->executeCommand('doctrine:migrations:migrate ' . $toVersion);
}
}
示例迁移测试:
class Version20180222232445_MyMigrationTest extends DatabaseMigrationTestCase {
/** @before */
public function prepare() {
$this->loadDump('2018-02-20');
$this->migrate('20180222232445');
}
public function testMigratedSomeData() {
$em = $this->container->get(EntityManagerInterface::class);
$someRow = $em->getConnection()->executeQuery('SELECT * FROM myTable WHERE id = 1')->fetch();
$this->assertEquals(1, $someRow['id']);
// check other stuff if it has been migrated correctly
}
}
我正在开发一个项目,该项目在开发环境中没有生产数据库的副本。
有时我们会遇到数据库迁移问题 - 它们传递开发数据库但在 production/testing 中失败。
这通常是因为开发环境数据是从使用最新实体的装置加载的 - 正确填充所有表格。
是否有任何简单的方法来确保 Doctrine Migration(s) 将在生产中通过?
您是否 have/know 有任何方法可以编写自动测试以确保在不下载 production/testing 数据库和 运行 手动迁移的情况下正确迁移数据?
我想避免将 production/testing 数据库下载到开发机器,这样我就可以检查迁移,因为该数据库包含私有数据并且它可能非常大。
我已经为 Doctrine Migrations 想出了简单的 "smoke tests"。
我有 PHPUnit 测试执行以下步骤:
- 跌落测试数据库
- 创建测试数据库
- 加载迁移(创建模式)
- 加载夹具(模拟生产数据)
- 迁移到一些旧版本
- 迁移回最新版本
这样我可以测试我们最近遇到的主要问题。
可以在我的博客上找到 PHPUnit 测试示例:http://damiansromek.pl/2015/09/29/how-to-test-doctrine-migrations/
首先,您需要在迁移前的状态下创建示例数据库转储。对于 MySQL 使用 mysqldump。对于 postgres pg_dump,例如:
mysqldump -u root -p mydatabase > dump-2018-02-20.sql
pg_dump -Upostgres --inserts --encoding utf8 -f dump-2018-02-20.sql mydatabase
然后为所有迁移测试创建一个摘要 class(我假设您已经在 config_test.yml
中为集成测试配置了一个单独的数据库):
abstract class DatabaseMigrationTestCase extends WebTestCase {
/** @var ResettableContainerInterface */
protected $container;
/** @var Application */
private $application;
protected function setUp() {
$this->container = self::createClient()->getContainer();
$kernel = $this->container->get('kernel');
$this->application = new Application($kernel);
$this->application->setAutoExit(false);
$this->application->setCatchExceptions(false);
$em = $this->container->get(EntityManagerInterface::class);
$this->executeCommand('doctrine:schema:drop --force');
$em->getConnection()->exec('DROP TABLE IF EXISTS public.migration_versions');
}
protected function loadDump(string $name) {
$em = $this->container->get(EntityManagerInterface::class);
$em->getConnection()->exec(file_get_contents(__DIR__ . '/dumps/dump-' . $name . '.sql'));
}
protected function executeCommand(string $command): string {
$input = new StringInput("$command --env=test");
$output = new BufferedOutput();
$input->setInteractive(false);
$returnCode = $this->application->run($input, $output);
if ($returnCode != 0) {
throw new \RuntimeException('Failed to execute command. ' . $output->fetch());
}
return $output->fetch();
}
protected function migrate(string $toVersion = '') {
$this->executeCommand('doctrine:migrations:migrate ' . $toVersion);
}
}
示例迁移测试:
class Version20180222232445_MyMigrationTest extends DatabaseMigrationTestCase {
/** @before */
public function prepare() {
$this->loadDump('2018-02-20');
$this->migrate('20180222232445');
}
public function testMigratedSomeData() {
$em = $this->container->get(EntityManagerInterface::class);
$someRow = $em->getConnection()->executeQuery('SELECT * FROM myTable WHERE id = 1')->fetch();
$this->assertEquals(1, $someRow['id']);
// check other stuff if it has been migrated correctly
}
}