PHPUnit-断言查询从数据库返回良好的数据 [英] PHPUnit - Asserting that a query returns the good data from a database
问题描述
我正在测试一个Factory,它可以简单地检索新闻系统的所有"帖子"。我将把这个示例简化为尽可能简单的内容:
$newsFactory->getAllNews();
表格如下:
+---------+---------------------+-------------+
| news_id | news_publishedDate | news_active |
+---------+---------------------+-------------+
| 1 | 2010-03-22 13:20:22 | 1 |
| 2 | 2010-03-23 13:20:22 | 1 |
| 14 | 2010-03-23 13:20:22 | 0 |
| 15 | 2010-03-23 13:20:22 | 1 |
+---------+---------------------+-------------+
我想测试该行为;目前,我们只关注第一个:
- 确保查询只返回NEWS_ACTIVE=1
- 确保查询将返回按News_PublishedDate排序的元素,从最新到旧。
所以我创建了一个dbData.xml
我认为是好的测试数据的数据集:
<?xml version="1.0" encoding="UTF-8" ?>
<dataset>
<table name="news">
<column>news_id</column>
<column>news_publishedDate</column>
<column>news_active</column>
<row>
<value>1</value>
<value>2010-03-20 08:55:05</value>
<value>1</value>
</row>
<row>
<value>2</value>
<value>2010-03-20 08:55:05</value>
<value>0</value>
</row>
<row>
<value>3</value>
<value>2011-03-20 08:55:05</value>
<value>1</value>
</row>
</table>
</dataset>
好的,让我们只检查第一个测试(不从XML数据集中返回news_id
#2)
我必须扩展PHPUnit_Extensions_Database_TestCase
类才能创建NewsFactoryTest类:
<?php
require_once 'PHPUnit/Extensions/Database/TestCase.php';
class NewsFactoryTest extends PHPUnit_Extensions_Database_TestCase
{
protected $db;
protected function getConnection()
{
$this->db = new PDO('mysql:host=localhost;dbname=testdb', 'root', '');
return $this->createDefaultDBConnection($this->db, 'testdb');
}
protected function getDataSet()
{
return $this->createXMLDataSet(dir(__FILE__) . DIRECTORY_SEPARATOR . 'dbData.xml');
}
public function testGetNewsById()
{
$newsFactory = new NewsFactory($this->db);
$news = $newsFactory->getNewsById();
// ???
$this->assertEquals(2, count($news), "Should return only 2 results");
}
}
我的主要问题是如何设置该测试?
具体来说,我试着理解:
- 我应该创建一个testdb数据库,还是完全是模拟/虚拟的?
- 我看过很多使用
sqlite::memory:
的例子,用SQLite测试基于MySQL的查询是个好主意吗?我可以改用mysql::memory:
吗? - 如果是真正的数据库,如何在每次测试运行之前还原数据库中
dbData.xml
的所有数据?
- 我看过很多使用
- 我应该在哪里调用
getConnection()
和getDataSet()
?
感谢阅读和分享您的知识!
推荐答案
我在我们的项目中设置了数据库测试,以下是对我们有用的一些答案和经验:
我应该创建一个testdb数据库,还是全部是模拟的/虚拟的?
我在开始时也问了同样的问题,我们都知道这确实是一个真正的数据库在运行。
我看过很多使用SQLite::Memory:的例子,用SQLite测试基于MySQL的查询是个好主意吗?我可以改用MySQL::Memory:吗?
我尝试使用SQLite来提高性能,但发现SQL会有很大的不同,不能在现有代码中随处使用。我能够对大多数表使用MySQL内存引擎(对于某些表,如BLOB列则不可能)。
如果是真正的数据库,如何在每次测试运行之前还原数据库中的所有数据?
我编写了一个脚本,从远程测试服务器调用模式及其所有表的mysqlump,将它们插入本地服务器,并将所有可能的表引擎转换为内存。这确实需要时间,但由于架构不会在不同的测试之间更改,因此它只在最顶层的TestSuite上运行一次,或者根据开发人员在其本地系统上的需要单独运行一次。
数据集在每次测试开始时加载,由于表已经存在并且在内存中,因此测试之间的插入和截断速度很快。
我应该在哪里调用getConnection()和getDataSet()?
我们已经有一个扩展了TestCase的帮助器类,所以我不能使用PHPUnit_Extensions_Database_TestCase。我将设置函数添加到该助手类中,并且从未调用或必须实现getDataSet()。我确实使用了getConnection()从Assert函数中修改的数据创建数据集。
/**
* @param PHPUnit_Extensions_Database_DataSet_IDataSet $expected_data_fixture
* @param string|array $tables
*/
protected function assertDataFixturesEqual($expected_data_fixture, $tables){
if(!is_array($tables)){
$tables = array($tables);
}
PHPUnit_Extensions_Database_TestCase::assertDataSetsEqual($expected_data_fixture, $this->DbTester->getConnection()->createDataSet($tables));
}
编辑: 我发现我用作PHPUnit文档的一些资源的书签有点缺失:
http://www.ds-o.com/archives/63-PHPUnit-Database-Extension-DBUnit-Port.html
http://www.ds-o.com/archives/64-Adding-Database-Tests-to-Existing-PHPUnit-Test-Cases.html
这篇关于PHPUnit-断言查询从数据库返回良好的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!