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

11

我有一个Symfony 4应用程序,使用Doctrine和Doctrine migrations。我正在引入Codeception来运行API测试,并且需要在测试运行之前运行迁移。由于我正在使用Doctrine2模块,因此我不希望同时包含DB模块,因为它对测试没有必要,并且需要在两个不同的位置配置测试数据库。

我目前正在使用Symfony模块,我注意到Laravel模块具有run_database_migrations配置选项。

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


编辑 我已经找到了解决方案,虽然它可以工作,但远非理想。通过使用Codeception定制,我创建了以下扩展名,基本上手动执行底层的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迁移来处理DB。- https://codeception.com/docs/modules/Db#sql-data-dump
3个回答

10

我尝试了一段时间来尝试几种不同的方法来实现这个目标。最初我使用了RunProcess,但是尽管使用了sleep配置,它似乎会导致数据库被删除而无法重新创建的问题。最终我只更新了现有的扩展,改用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或更高级别还会显示DB和Migration命令的输出);


你不应该针对一个专门用于测试的数据库进行目标定位吗?使用参数 --env=test - Starwave
@Starwave 是的 - 我是这样想的,所以每次都想重新构建它。 - Chris Brown

2
我通常会创建一个bash脚本或Makefile来完成这个任务。

bash命令

我的./runtests.sh脚本包含以下内容

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

Makefile

Same with Makefile

.FOO: testsuite
testsuite:
    ./runtests.sh

或者

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

为什么我更喜欢Makefile

最近,我在我的.bash_profile中添加了这个脚本,使我能够从bash中自动完成所有在makefile中制作的目标(非常容易,因为您不再需要记住所有命令,只需使用 make 和 tab )。

complete -W“`grep -oE' ^ [a-zA-Z0-9_.-] +:([^ =] | $)' Makefile | sed's / [^ a-zA-Z0-9_.-] * $ // '`”make

因此,..您可以创建如下目标:

  • runtests
  • runtests_with_fixtures
  • migrations
  • runtests_with_migrations
  • ...

等等

我的建议是创建您自己的自定义且易于运行命令的方式。


这里是使用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

感谢您深入的回答 - 如果必要,我很高兴以这种方式推进,但理想情况下,我希望测试套件来处理数据库(创建、迁移),而不是外部。因为测试套件已经在测试环境(而不是开发环境)下运行并处理清理/撤销操作。我上面提供的笨拙解决方案可以帮我实现这一点,因此运行测试不需要任何先前设置,所有内容都在测试命令中处理,并使用测试环境变量设置了DB,这些变量也适用于测试本身的运行。 - Chris Brown

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]);

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