如何测试Doctrine Migrations?

9

我正在处理一个项目,该项目在开发环境中没有生产数据库的副本。

有时我们会遇到数据库迁移问题-它们通过开发数据库,但在生产/测试环境中失败。

这通常是因为Dev环境数据是从使用最新实体的Fixture加载的-正确填充所有表。

是否有任何简单的方法可以确保Doctrine Migration在生产环境中通过?

您是否有/了解任何编写自动测试的方法,以确保数据将正确迁移到而无需下载生产/测试数据库并手动运行迁移?

我想避免下载生产/测试数据库到开发机器上以检查迁移,因为该数据库包含私有数据且可能相当大。


如果你正在使用Git,你是否考虑过返回到最新的生产版本,重新创建你的数据库、固定数据和迁移,并且升级到最新版本以运行新的迁移。然而,唯一可靠的测试是使用生产数据。 - Léo Benoist
2个回答

6

首先,您需要在迁移之前创建一个样本数据库转储。对于MySQL,请使用mysqldump。对于PostgreSQL,请使用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

接下来创建一个抽象类,用于所有迁移测试(假设在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
    }
}

1
我已经想出了Doctrine Migrations的简单“烟雾测试”。
我有一个PHPUnit测试执行以下步骤:
- 删除测试数据库 - 创建测试数据库 - 加载迁移(创建模式) - 加载夹具(模仿生产数据) - 迁移到旧版本 - 迁移回最新版本
这样我就可以测试我们最近遇到的主要问题。
PHPUnit测试示例可以在我的博客中找到:http://damiansromek.pl/2015/09/29/how-to-test-doctrine-migrations/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接