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

问题描述 投票:0回答:4

我有一个 Symfony 4 应用程序和带有 Doctrine 迁移的 Doctrine。我将引入 Codeception 来运行 API 测试,并且需要在测试运行之前运行迁移。由于我使用的是 Doctrine2 模块,我真的不想包含 DB 模块,因为测试不需要它,并且需要在两个不同的位置配置测试数据库。

我目前正在使用 Symfony 模块,我注意到 Laravel 模块 有一个

run_database_migrations
配置选项。

在测试之前在 Symfony 应用程序中处理运行 Doctrine 迁移命令的最佳方法是什么? (

bin/console doctrine:migrations:migrate -n
为具体命令)。


编辑我有一个解决方案,虽然它有效,但远非理想。通过使用 Codeception Customization 我创建了以下扩展,基本上手动

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

php symfony doctrine-orm codeception
4个回答
10
投票

我花了一段时间尝试了几种不同的方法来实现这一目标。我最初使用 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
或更高版本还显示数据库和迁移命令的输出);


2
投票

我总是创建一个 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 中创建的所有目标(非常简单,因为您不再需要记住所有命令,而只需记住

make
tab
)。

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

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

  • 运行测试
  • 运行测试_with_fixtures
  • 迁移
  • runtests_with_migrations
  • ...

等等

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


这是一种使用 gin 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

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

0
投票

我的决定:

<?php

declare(strict_types=1);

namespace Test\Support\Extension;

use Codeception\Event\SuiteEvent;
use Codeception\Events;
use Codeception\Extension;
use Codeception\Module\Symfony;

class DatabaseInitializationExtension extends Extension
{
    public static array $events = [Events::SUITE_INIT => ['initialize', 100]];

    public function initialize(SuiteEvent $event): void
    {
        $modules = $event->getSuite()->getModules();

        $symfony = $modules['Symfony'] ?? null;

        if ($symfony instanceof Symfony) {
            $symfony->runSymfonyConsoleCommand('d:d:drop', ['--force' => true, '--if-exists' => true]);
            $symfony->runSymfonyConsoleCommand('d:d:create', ['--if-not-exists' => true]);
            $symfony->runSymfonyConsoleCommand('d:m:m', ['-n' => true]);
        }
    }
}

添加到

codeception.yml

extensions:
    enabled:
        - Test\Support\Extension\DatabaseInitializationExtension

如果

--env=test
丢失,请不要担心。如果
environment: 'test'
参数在
Symfony
模块中,则将针对相应的环境执行命令。

© www.soinside.com 2019 - 2024. All rights reserved.