database - PHPUnit - 断言查询从数据库返回正确的数据

标签 database phpunit

我正在测试一个工厂,它可以简单地检索新闻系统的所有“帖子”。我会将示例简化为尽可能简单的内容:

$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()

感谢您阅读并分享您的知识!

最佳答案

我在我们的项目中设置了数据库测试,以下是一些对我们有用的答案和经验教训:

Should I create a testdb database or is that all emulated/virtual ?

我一开始就问了同样的问题,我们都知道它确实是一个正在运行的真正的数据库。

I've seen many examples using sqlite::memory: , is it a good idea to test MySQL based query with sqlite ? Can I use mysql::memory: instead ?

我尝试使用 sqlite 来提高性能,但发现 SQL 的差异很大,无法在我们现有的代码中随处使用。我能够对大多数表使用 MySQL MEMORY 引擎(对于某些表(例如 BLOB 列)是不可能的)。

If it's a real DB, how do I restore all the data from dbData.xml in the DB before each test run ?

我编写了一个脚本,从我们的远程测试服务器调用架构及其所有表的 mysqldump,将它们插入本地服务器,并将所有可能的表引擎转换为 MEMORY。这确实需要时间,但由于模式在测试之间不会改变,因此它只在最顶层的 TestSuite 上运行一次,或者根据开发人员的需要在本地系统上单独运行。

数据集在每次测试开始时加载,并且由于表已经存在并且在内存中,因此测试之间的插入和截断速度很快。

Where am I supposed to call getConnection() and getDataSet() ?

我们已经有一个扩展 TestCase 的帮助程序类,因此我无法使用 PHPUnit_Extensions_Database_TestCase。我将设置函数添加到该帮助程序类中,并且从未调用或必须实现 getDataSet()。我确实使用 getConnection() 从断言函数中修改的数据创建数据集。

/**
 * @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

关于database - PHPUnit - 断言查询从数据库返回正确的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5411489/

相关文章:

laravel - 测试 Laravel-Excel 下载

mysql - 无法迁移数据库(laravel)

android - 在游标数据中添加值

c# - SQL Server CE 或 Access for a portable database with c#?

javascript - 在一个查询中更新多个表

php - Selenium、XPath 节点集和 PHPUnit

PHPUnit 和 Composer : [InvalidArgumentException] Command "path/to/test" is not defined

phpunit - 如何在 PHPUnit 测试中使用 csv 文件

php - 运行PHPUnit测试时如何避免内部调用函数?以及如何为内部性能设置模拟数据?

database - 一个关系可以有不同长度的候选键吗?