Php Symfony2中的数据库测试实践?如何隔离?
目前使用Symfony2测试数据库交互的最佳实践是什么?我有一个简单的积垢设置,我想确保我的测试是正常的。现在,我有4个测试,每个测试都确保创建、更新、删除和列出操作正常进行 在我的测试用例中,我有两种神奇的方法,构造和析构函数。在它们内部,我使用'php app/console…'调用exec(),以便创建数据库、创建模式,然后删除数据库。然而,这是非常缓慢的,而且当我有多个测试用例时,它总是发生Php Symfony2中的数据库测试实践?如何隔离?,php,unit-testing,symfony,Php,Unit Testing,Symfony,目前使用Symfony2测试数据库交互的最佳实践是什么?我有一个简单的积垢设置,我想确保我的测试是正常的。现在,我有4个测试,每个测试都确保创建、更新、删除和列出操作正常进行 在我的测试用例中,我有两种神奇的方法,构造和析构函数。在它们内部,我使用'php app/console…'调用exec(),以便创建数据库、创建模式,然后删除数据库。然而,这是非常缓慢的,而且当我有多个测试用例时,它总是发生 当涉及到数据库测试和隔离此类测试时,我应该如何进行?数据库测试总是很慢,因为您需要在每次测试之前
当涉及到数据库测试和隔离此类测试时,我应该如何进行?数据库测试总是很慢,因为您需要在每次测试之前/之后创建/删除模式。为避免不必要的操作,您可以:
- 在“setUpBeforeClass”方法中创建架构李>
- 确保您的4个测试在一个带有'@depend'注释的线程中启动李>
- 在“tearDownAfterClass”方法中删除架构
无论如何,“_-construct”和“_-destruct”不应该在phpunit测试用例中使用,相反,您应该使用“setUp”和“tearDown”。我认为最好总是从干净开始,以确保测试完全隔离。为此,我只是在每次测试之前构建数据库结构,然后用给定测试所需的装置填充它 请注意,我只构建所需的数据库表,并且只插入所需的装置。这比加载一个大的数据库转储要快一点。它也更干净,因为测试不共享夹具(这使它们更易于维护) 我有一个名为KernelAwareTest的基本测试用例类,它帮助我构建模式。你可以在gist上找到它:
setUp()
引导Symfony内核并将对它的引用存储在类属性中(以及对DIC和实体管理器的引用)。还可以调用generateSchema()
,以生成数据库模式(它使用来自Doctrine的模式工具)
默认情况下,它为实体管理器已知的所有实体生成数据库结构。通过重写getMetadatas()
方法,可以在测试类中更改此行为
附言:我尝试使用内存数据库(sqlite),但并不完美。无论如何,对生产中使用的数据库运行测试可能更好。这个问题已经很老了,但今天仍然有效,下面是我的经验以及我今天在Symfony项目中如何处理它 我开始在测试中使用SQLite内存数据库,并在每个测试用例之前重建db schema+插入的fixture。这有两个主要缺点:
- 还是太慢了:(
- 在dev&prod上,我使用了Mysql,这很快就成了一个问题,因为SQLite没有所需的所有特性,有时行为也会有所不同
从一段时间以来,它也被用于symfony演示项目。在本地机器上测试是一件痛苦的事,所以我开始使用ci system buddy.works(有免费的单机版),为此我需要自己解决这个问题 结果是:
- 所有测试都有效
- 测试正在生产sql数据上运行
- 测试是分开运行的(不是在开发或生产环境中),所以我可以这样做 我想要什么数据库
- 所有对git的推送都经过测试,如果有什么东西坏了,我会收到通知
- 部署分支的所有推/拉请求都会自动上载到生产
/**
*这是Robo task runner的项目控制台命令配置。
*
*@见http://robo.li/
*/
类RoboFile扩展\Robo\Tasks
{
函数loadDb(){
$this->taskExecStack()
->stopOnFail()
->exec(“mysql-h mariadb-u root-pqwerty-e‘创建数据库测试’”)
->exec(“mysql-h mariadb-u root-pqwerty testrun();
}
函数prepareDb(){
$this->taskExecStack()
->stopOnFail()
->exec(“cp-app/config/parameters-test.yml-app/config/parameters.yml”)
->run();
$this->taskreplaceinfle('app/config/parameters.yml'))
->from('数据库\主机:127.0.0.1')
->至(“数据库_主机:'mariadb'”)
->run();
$this->taskreplaceinfle('app/config/parameters.yml'))
->from('database_user:dbuser'))
->至(“数据库用户:'root'))
->run();
$this->taskreplaceinfle('app/config
doctrine:
dbal:
driver: pdo_sqlite
path: :memory:
memory: true
/**
* This is project's console commands configuration for Robo task runner.
*
* @see http://robo.li/
*/
class RoboFile extends \Robo\Tasks
{
function loadDb(){
$this->taskExecStack()
->stopOnFail()
->exec(" mysql -h mariadb -u root -pqwerty -e 'create database test' ")
->exec(" mysql -h mariadb -u root -pqwerty test < test.sql ")
->run();
}
function prepareDb(){
$this->taskExecStack()
->stopOnFail()
->exec("cp app/config/parameters-test.yml app/config/parameters.yml")
->run();
$this->taskReplaceInFile('app/config/parameters.yml')
->from('database_host: 127.0.0.1')
->to("database_host: 'mariadb'")
->run();
$this->taskReplaceInFile('app/config/parameters.yml')
->from('database_user: dbuser')
->to("database_user: 'root'")
->run();
$this->taskReplaceInFile('app/config/parameters.yml')
->from('database_password: 123')
->to("database_password: 'qwerty'")
->run();
}