【问题标题】:Symfony3 create database for unittestsSymfony 3 为单元测试创​​建数据库
【发布时间】:2017-11-24 22:38:52
【问题描述】:

晚上好 :-)

我现在正在学习 Symfony(3),我想在我的课程中使用测试。我读过单元测试不应该使用数据库,而是模拟它的对象。

但尽管如此,我想在 setUp()/KernelTestCase 数据库(例如 MySQL)中创建并读取其内容以获取文件,接下来进行测试(简单 -unittests),然后在 tearDown().

是否可以使用转储的 MySQL 文件?

什么是最好的(?懒惰的)方法?

我宁愿阅读准备好的(转储的)类 SQL 文件,然后从 ORM 类中读取“更新:模式”。在 Symfony3 中将文件放在哪里?如何阅读并创建数据库内容?

请。帮帮我。

【问题讨论】:

  • 超级,downwote 比 help 更简单

标签: database symfony unit-testing


【解决方案1】:

我多年来一直在使用它:

重复!这对我来说是最有效的,因为您只加载一次测试数据; NOT 用于每个测试。当然,您将不得不更加仔细地考虑您的测试场景。

例如,考虑一个 crud 测试:

测试1

  • 检查列表是否有 1 项(由固定装置加载)

测试2

  • 创建项目
  • 检查列表是否有 2 个项目

测试3

  • 删除元素
  • 检查列表是否有 1 项

所以测试必须完全按照这个顺序执行。如果您在每个测试之间加载固定装置,则不必处理该顺序,但这会使您的测试变慢。

我觉得加载一次固定装置更好,因为它会像用户通常做的那样:创建、删除、更新项目...因此您可以检查每个操作之间没有副作用。

我的加载夹具脚本:

#!/bin/bash
echo "##########################################################################"
echo "# Refresh data model, reload all reference data, load fixtures,          #"
echo "# validate schema for the dev env.                                       #"
echo "##########################################################################"

php bin/console doctrine:database:create --if-not-exists --env=dev
php bin/console doctrine:schema:drop --force --env=dev
php bin/console doctrine:schema:create --env=dev
php bin/console doctrine:schema:validate --env=dev
php bin/console doctrine:fixtures:load -n --env=dev
echo -e " --> DONE\n"

或者,如果您想为 SQL 文件加载数据库,请使用:

php bin/console doctrine:database:import db.sqb --env=dev

而不是加载夹具命令。

然后,启动测试:

./bin/simple-phpunit --debug --verbose $1

$1 是指定要加载的测试套件的参数。 (main, front, API, backend...) 您可以在 phpunit.xml.dist 文件中进行参数化。 (你可以省略它来运行所有的测试)

【讨论】:

  • 非常感谢您的帮助。我必须重新考虑我对测试的想法。一开始我打算简单地从以前准备好的转储文件 .sql 中加载 MySQL 数据库。问题是,我不知道,如何从 Symfony DB 凭证中挑选出来......我的班级对一些表格内容执行分析,这种方式(下载准备好的.sql进行测试)似乎是最佳的。
  • 什么也可以使用doctrine:database:import 命令从SQL 文件中导入数据库。
  • 请用doctrine:database:import 指出简短的解决方案...我找不到任何东西...对我来说可以理解...但是:-(
  • 通过数据库的 sql 脚本运行:php bin/console doctrine:database:import db.sql --env=dev(替换 db.sql)。
  • 非常感谢!!!这个作品!!! wiks@asus:/var/www/sfproject_v1$ php bin/console doctrine:database:import tests/dbcontent/wiks_comunication_5tbl.sql --env=dev Processing file '/var/www/sfproject_v1/tests/dbcontent/wiks_comunication_5tbl.sql'... OK!
【解决方案2】:

我的解决方案是: 这会将所有 SQL 文件加载到 MySQL TEST DB - 在'parameters_test.yml' 中定义并处理测试并在下一次测试之前删除所有数据库表,并在下一次测试之前再次删除......它可以通过命令@987654326 以更短和更正确的方式完成@正如@Tokeeen.com 所说。谢谢你的帮助。

// tests/AppBundle/Repository/BotsDbTest.php

<?php
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Yaml\Parser;

class BotsDbTest extends KernelTestCase
{
    private $doctr;
    private $db_cred;
    private $db;

    /**
     * {@inheritDoc}
     */
    protected function setUp()
    {
        $kernel = self::bootKernel();
        $this->doctr = $kernel->getContainer()
            ->get('doctrine')
            ->getManager();        

        // for tests with loaded content
        $this->db = new \AppBundle\Wiks\BotsDb(); 

        // https://symfony.com/doc/current/bundles/extension.html
        // get DB credientals from "parameters_test.yml":
        $configDirectories = array( 'app/config' );
        $locator = new FileLocator( $configDirectories );
        $yamlUserFiles = $locator->locate( 'parameters_test.yml', null, false );        
        // https://davidegan.me/parse-yaml-in-php-using-symfony-yaml/
        $yaml = new Parser();
        $yaml_array = $yaml->parse( file_get_contents( $yamlUserFiles['0'] ) );
        // needen DB is the second in Symfony - as database2 in file "parameters_test.yml":
        $prefix_db = 'database2';
        // looking for all keys with suffix: eq: 'database2_host'
        $needed_sufix = [ 'host', 'port', 'name', 'user', 'password' ];
        $this->db_cred = array();
        foreach ( $yaml_array[ 'parameters' ] as $key => $value ) {
            if ( strpos( $key, $prefix_db ) !== false ) {
                foreach ( $needed_sufix as $needed_key ) {
                    if ( strpos( $key, $needed_key ) !== false ) {
                        $this->db_cred[ $needed_key ] = $value;
                    }
                }
            }
        }
        if ( count( $this->db_cred ) == count( $needed_sufix ) ) {
            // check is all found
            /*Array (
                [host] => 127.0.0.1
                [port] => 
                [name] => db_name
                [user] => user_name
                [password] => ***
            ) */            
            $finder = new Finder();
            // find and put into mysql all files as prepared content to tests
            $finder->files()->name('*.sql');
            foreach ( $finder->in( array( 'tests/dbcontent' ) ) as $file ) {
                $shell_command = 'mysql --user='.$this->db_cred['user'].' --password='.$this->db_cred['password'];
                $shell_command .= ' '.$this->db_cred['name'].'< '.$file->getRealPath();
                shell_exec( $shell_command );
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    protected function tearDown()
    {
        parent::tearDown();
        // remoove DB content ( all tabels ):
        $shell_command = 'mysqldump --user='.$this->db_cred['user'].' --password='.$this->db_cred['password'].' ';
        $shell_command .= '--add-drop-table --no-data '.$this->db_cred['name'].' | ';
        $shell_command .= 'grep -e \'^DROP \| FOREIGN_KEY_CHECKS\' | ';
        $shell_command .= 'mysql --user='.$this->db_cred['user'].' --password='.$this->db_cred['password'].' '.$this->db_cred['name'];
        shell_exec( $shell_command );
        $this->doctr->close();
        $this->doctr = null; // avoid memory leaks
    }


    /** tests, tests, tests...
     * 
     */
    public function test_getBots()
    {
        $res = $this->db->getBots( $this->doctr );
        $this->assertEquals(5, count( $res ));
        [...]

有用的链接:

How to remove all MySQL tables from the command-line without DROP database permissions?

https://davidegan.me/parse-yaml-in-php-using-symfony-yaml/

https://symfony.com/doc/current/components/finder.html

https://symfony.com/doc/current/bundles/extension.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多