9

開発環境に本番 DB のコピーがないプロジェクトに取り組んでいます。

DB の移行で問題が発生することがあります。開発用の DB は渡されますが、運用環境/テストでは失敗します。

多くの場合、開発環境データは、最新のエンティティを使用するフィクスチャからロードされ、すべてのテーブルが適切に埋められるためです。

Doctrine Migration(s) が本番環境で成功することを確認する簡単な方法はありますか?

本番/テスト用 DB をダウンロードして手動で移行を実行しなくても、データが適切に移行されることを確認する自動テストを作成する方法を知っていますか?

DB にはプライベート データが含まれており、非常に大きくなる可能性があるため、移行を確認できるように、運用/テスト用 DB を開発マシンにダウンロードすることは避けたいと考えています。

4

2 に答える 2

5

まず、移行前の状態のサンプル データベース ダンプを作成する必要があります。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

次に、すべての移行テスト用の抽象クラスを作成します ( で統合テスト用に別のデータベースを構成したと仮定します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
    }
}
于 2018-02-20T20:29:06.437 に答える