Codeception& Symfony - 在测试之前运行Doctrine迁移

时间:2018-04-25 20:15:59

标签: php symfony doctrine-orm codeception

我有一个Symfony 4应用程序和带有Doctrine迁移的Doctrine。我正在介绍用于运行API测试的Codeception,并且需要在测试运行之前运行迁移。由于我使用的是Doctrine2 module,我不想也包括DB module,因为测试不需要它,并且需要在两个不同的位置配置测试数据库。

我目前正在使用Symfony module,我注意到Laravel module有一个run_database_migrations配置选项。

在测试之前处理在Symfony应用程序中运行Doctrine迁移命令的最佳方法是什么? (bin/console doctrine:migrations:migrate -n是特定命令)。

编辑我已经找到了一个解决方案,尽管它有效,但远非理想。通过使用Codeception Customisation,我创建了以下基本上手动exec基础Symfony命令的扩展。

class DatabaseMigrationExtension extends Extension
{
    public static $events = [
        Events::SUITE_BEFORE => 'beforeSuite',
    ];

    public function beforeSuite(SuiteEvent $e)
    {
        echo(exec('bin/console doctrine:database:drop --force') . PHP_EOL);
        echo(exec('bin/console doctrine:database:create') . PHP_EOL);
        echo(exec('bin/console doctrine:migrations:migrate -n') . PHP_EOL);
    }
}

编辑2 这样做的目的基本上是将类似的功能复制到Codeception DB模块的功能,这允许您提供它在测试中自动使用的数据库的SQL转储,但是而是使用Doctrine迁移来处理数据库。 - https://codeception.com/docs/modules/Db#sql-data-dump

3 个答案:

答案 0 :(得分:2)

我花了一些时间尝试了几种不同的方法来实现这一目标。我最初使用RunProcess但是这似乎导致了数据库被删除而没有重新创建的偶发问题,尽管使用了睡眠配置。我最后只是更新现有的扩展以使用CLI模块,它可以根据需要工作(无需创建脚本或运行多个命令),而无需使用exec

最终延期;

class DatabaseMigrationExtension extends Extension
{
    public static $events = [
        Events::SUITE_BEFORE => 'beforeSuite',
    ];

    public function beforeSuite()
    {
        try {
            /** @var \Codeception\Module\Cli $cli */
            $cli = $this->getModule('Cli');

            $this->writeln('Recreating the DB...');
            $cli->runShellCommand('bin/console doctrine:database:drop --if-exists --force');
            $cli->seeResultCodeIs(0);
            $cli->runShellCommand('bin/console doctrine:database:create');
            $cli->seeResultCodeIs(0);

            $this->writeln('Running Doctrine Migrations...');
            $cli->runShellCommand('bin/console doctrine:migrations:migrate --no-interaction');
            $cli->seeResultCodeIs(0);

            $this->writeln('Test database recreated');
        } catch (\Exception $e) {
            $this->writeln(
                sprintf(
                    'An error occurred whilst rebuilding the test database: %s',
                    $e->getMessage()
                )
            );
        }
    }
}

并注册;

// codeception.yml
extensions:
    enabled:
        - \DatabaseMigrationExtension

输出(-vv或更高版本也会显示数据库和迁移命令的输出);

答案 1 :(得分:1)

我总是创建一个bash脚本来执行此操作,或者创建一个Makefile。

bash命令

我的./runtests.sh脚本包含

#!/bin/bash
./bin/console command:for:migrations
./bin/phpunit

生成文件

与Makefile相同

.FOO: testsuite
testsuite:
    ./runtests.sh

.FOO: testsuite
testsuite:
    ./bin/console command:for:migrations
    ./bin/phpunit

为什么我更喜欢Makefile

最近我在.bash_profile中添加了这个脚本,允许我从bash中自动完成makefile中的所有目标(非常简单,因为你不再需要记住所有命令,只是maketab )。

  

完成-W"`grep -oE' ^ [a-zA-Z0-9 _.-] + :( [^ =] | $)' Makefile | sed' s / [^ a-zA-Z0-9 _.-] * $ //'`"使

因此,你可以创建像:

这样的目标
  • runtests
  • runtests_with_fixtures
  • 迁移
  • runtests_with_migrations
  • ...

等等

我的建议是创建自定义且简单的方法来运行命令。

这里有一种方法来运行全部或仅一个命令usgin make

.FOO: dropforce
dropforce:
    bin/console doctrine:database:drop --force

.FOO: dbcreate
dbcreate:
    bin/console doctrine:database:create

.FOO: migrate
migrate:
    bin/console doctrine:migrations:migrate

.FOO: suite
suite: dropforce dbcreate migrate

答案 2 :(得分:1)

有了Codeception 4,您就可以在没有Cli模块的情况下做到这一点:

$symfony = $this->getModule('Symfony');

$symfony->runSymfonyConsoleCommand('doctrine:database:drop',['--if-exists'=>true, '--force'=>true]);
$symfony->runSymfonyConsoleCommand('doctrine:database:create');
$symfony->runSymfonyConsoleCommand('doctrine:migrations:migrate', ['--no-interaction'=>true]);