8 数据库测试
PHPUnit支持的访问数据库:
- MySQL
- PostgreSQL
- Oracle
- SQLite
- IBM DB2
- Microsoft SQL Server
当然,对应的拓展需要安装好,比如pdo
。
环境配置
官网上没有介绍这里,所以这里是我自己搭建环境过程中找到的一些问题。
首先,composer
默认帮你安装的是最新版本的PHPUnit,现在是8.0.1
,但是phpunit/dbunit
只能在PHPUnit7.*
版本中使用,所以你可能需要重装PHPUnit,这就是属于composer
的范畴,我是最简单把vendor
目录和composer.json
和composer.lock
文件删除了,接着运行下面的命令来安装的:
composer require phpunit/phpunit 7.5.x-dev
再来安装dbUnit
composer require phpunit/dbunit
但是他报了一个警告:
Package phpunit/dbunit is abandoned, you should avoid using it. No replacement was suggested.
好像是说这个包不再维护了,应该尽量避免使用它。但是我们这里只是学习,先用着吧。
数据库测试的四个阶段
清理数据库
简单来说,PHPUnit会对指定的表进行一次truncate
操作,将表清空。如何指定表接下来会讲。
建立基境
上面清除数据后,PHPUnit会讲你需要的数据插入到数据库中。 插入的方法下面会讲。
运行测试,验证结果,并拆除基境
这一部分就是靠你自己写代码判断数据是否正确插入了,但是和我原先预期不一样的是,我原本以为是靠我们编写待测试的代码来插入数据,其实是PHPUnit设定了很多数据类型,来插入这些指定的数据,所以和原先感觉有点不一样。
而最后的拆除基境,其实PHPUnit不会再对对应表执行一次truncate
操作。
下面来看一个实际的demo
设置连接方式
基础版
require_once __DIR__."/../../vendor/autoload.php";
use PHPUnit\Framework\TestCase;
class DataBaseTest extends TestCase{
use PHPUnit\DbUnit\TestCaseTrait;
protected $databaseType="mysql";
protected $host="127.0.0.1";
protected $user="root";
protected $password="1234qwer";
protected $databaseName="test";
/**
* 该方法会在 setUp 中调用一次
*/
protected function getDataSet()
{
// TODO: Implement getDataSet() method.
}
protected function getConnection()
{
// TODO: Implement getConnection() method.
$dsn=$this->databaseType.":host=".$this->host.";dbname=".$this->databaseName;
$pdo=new PDO($dsn,$this->user,$this->password);
return $this->createDefaultDBConnection($pdo);
}
}
这里的重点就是:use PHPUnit\DbUnit\TestCaseTrait;
需要实现它的两个抽象方法:
- getDataSet():这个方法需要返回一个指定的数据库初始数据,这个下一节再讲。
- getConnection():这个方法需要返回一个指定的数据库连接方式
这里是拿mysql为例,借助PDO
拓展进行连接,如果是其他类型的数据库的话,比如Orcale,则也可以使用PDO,只是配置修改一下而已。$this->createDefaultDBConnection($pdo);
则是返回一个PHPUnit需要的连接类型。
书上的例子是建议我们将这一层专门提取出来写在一个类里面,这样就不用在每个类中重复了,因为一般情况下我们测试时不会测试多个数据库。
再来就是数据库地址,账号密码等信息了,这里是使用硬编码的方式写在类中了,PHPUnit支持多个配置文件,所以也可以写在配置文件中:
使用配置文件修改连接方式
配置文件的demo
<?xml version="1.0" encoding="UTF-8" ?>
<phpunit>
<php>
<var name="DB_DSN" value="mysql:dbname=test;host=127.0.0.1" />
<var name="DB_USER" value="root" />
<var name="DB_PASSWD" value="password" />
<var name="DB_DBNAME" value="test" />
</php>
</phpunit>
这里的name
和value
都不是固定的,这里我们是借用PHPUnit的一个功能,在这里设定的值都会被写进$GLOBALS
中,如下所示:
require_once __DIR__."/../../vendor/autoload.php";
use PHPUnit\Framework\TestCase;
use PHPUnit\DbUnit\TestCaseTrait;
class DataBaseXMLTest extends TestCase{
use TestCaseTrait;
private static $pdo=null;// 单例模式
private $conn=null;// 这个值是我们人为设定的
protected function getDataSet()
{
// TODO: Implement getDataSet() method.
}
// 这里我们
final protected function getConnection()
{
if($this->conn==null){
if(self::$pdo==null){
self::$pdo=new PDO($GLOBALS['DB_DSN'], $GLOBALS['DB_USER'], $GLOBALS['DB_PASSWD']);
}
$this->conn=$this->createDefaultDBConnection(self::$pdo,$GLOBALS['DB_DBNAME']);
}
return $this->conn;
}
}
可以看到这里我们其实是从$GLOBALS
中读取数据,所以假设我们有2个配置文件:
- databaseSet1.xml
- databaseSet2.xml
那么当我们在命令行中使用参数:--configuration
指定配置文件时,我们就可以动态修改数据库的连接方式了:
phpunit --configuration databaseSet1.xml DataBaseXMLTest.php
phpunit --configuration databaseSet2.xml DataBaseXMLTest.php
设置初始数据
简单来说有以下几种方式:
- 基于给定文件的
- 基于数据库查询的
- 基于筛选和组合的
基于文件的
Flat XML Dataset
例子:
<?xml version="1.0" ?>
<dataset>
<guestbook id="1" content="Hello buddy!" user="joe" created="2010-04-24 17:15:23" />
<guestbook