phpunit-单元测试神器
在我们开发的时候,测试是必不可少的东西,那么有个好的测试工具才能让你测试的效率提升,现在就介绍下最近我发现的单元测试工具-phpunit吧.
phpunit
phpunit是php 轻量级的单元测试框架,只需要编写好单元测试代码,运行即可测试结果是否和预期结果一样,如果不一样则会报错.
官方中文文档:http://www.phpunit.cn/manual/current/zh_cn/installation.html
请根据官方文档的安装方法进行安装.
本人使用的是composer安装方式:
composer require --dev phpunit/phpunit ^7.5
复制
编写测试用例
api接口测试
为了方便发起http请求,本文还额外引入了curl组件:
composer require php-curl-class/php-curl-class
复制
假设我们需要测试/Index/index接口,正确调用后,接口会输出"hello world":
<?php
/**
* Created by PhpStorm.
* User: Tioncico
* Date: 2019/4/2 0002
* Time: 10:24
*/
namespace ApiTest\Index;
use App\HttpController\Index;
use Curl\Curl;
use PHPUnit\Framework\TestCase;
class IndexTest extends TestCase
{
public function testIndex()
{
$url = '127.0.0.1:9501/Index/index';//api地址
$curl = new Curl();
$data = [//get数据
'adminAccount' => 'testncl',
'adminName' => '宁成龙',
'adminPassword' => '123456',
];
$curl->setCookies([//设置cookie
'cookieName' => 1,
]);
$curl->get($url, $data);
if ($curl->response) {
var_dump($curl->response);
} else {
echo 'Error: ' . $curl->errorCode . ': ' . $curl->errorMessage . "\n";
}
$this->assertTrue(!!$curl->response);//断言结果是否为true,如果不为true则报错
$this->assertEquals('hello world', $curl->response);//断言结果是否等于hello world,如果不等于则报错
}
}
复制
php运行单元测试
php vendor/phpunit/phpunit/phpunit ./ApiTest/Index/IndexTest.php//后面的是你写的单元测试例子的路径
复制
类方法测试
假设我们写了一个类:
<?php
/**
* Created by PhpStorm.
* User: Tioncico
* Date: 2019/4/2 0002
* Time: 10:51
*/
class User
{
function add($data){
if (empty($data)){
return false;
}
return $data;
}
function get($id){
return [
'id'=>1,
'name'=>'test'
];
}
function delete($id){
return true;
}
}
复制
编写测试用例
<?php
/**
* Created by PhpStorm.
* User: Tioncico
* Date: 2019/4/2 0002
* Time: 10:53
*/
use PHPUnit\Framework\TestCase;
include "User.php";//引入User类,可使用自动加载省略这步
class UserTest extends TestCase
{
public function testGet()
{
$user = new User();
$data= $user->get(1);
$this->assertEquals('1',$data['id']);//断言返回的id为1
}
public function testAdd()
{
$user = new User();
$data = [
'id'=>1,
'name'=>'tioncico'
];
$this->assertEquals($data,$user->add($data));//断言传入data返回data
$this->assertFalse($user->add([]));//断言传入空数组返回false
}
public function testDelete()
{
$user = new User();
$data= $user->delete(1);
$this->assertTrue($data);//断言返回true
}
}
复制
断言
在上面的例子中,我们知道了断言
断言是编程术语,表示为一些布尔表达式,程序员相信在程序中的某个特定点该表达式值为真
例如上面的api接口,当正确调用时一定会输出"hello world",断言它将会输出hello world,如果没有输出该结果则代表断言出错
在phpunit中,还有其他的断言方法,例如:
布尔类型
方法名 |
含义 |
参数 |
返回值 |
---|---|---|---|
assertTrue |
断言为真 |
|
|
assertFalse |
断言为假 |
|
|
NULL类型
方法名 |
含义 |
参数 |
返回值 |
---|---|---|---|
assertNull |
断言为NULL |
|
|
assertNotNull |
断言非NULL |
|
|
数字类型
方法名 |
含义 |
参数 |
返回值 |
---|---|---|---|
assertEquals |
断言等于 |
|
|
assertNotEquals |
断言不等于 |
|
|
assertGreaterThan |
断言大于 |
|
|
assertGreaterThanOrEqual |
断言大于等于 |
|
|
assertLessThan |
断言小于 |
|
|
assertLessThanOrEqual |
断言小于等于 |
|
|
字符类型
方法名 |
含义 |
参数 |
返回值 |
---|---|---|---|
assertEquals |
断言等于 |
|
|
assertNotEquals |
断言不等于 |
|
|
assertContains |
断言包含 |
|
|
assertNotContains |
断言不包含 |
|
|
assertContainsOnly |
断言小于 |
|
|
assertLessThanOrEqual |
断言只包含 |
|
|
assertNotContainsOnly |
断言不只包含 |
|
|
数组类型
方法名 |
含义 |
参数 |
返回值 |
---|---|---|---|
assertEquals |
断言等于 |
|
|
assertNotEquals |
断言不等于 |
|
|
assertArrayHasKey |
断言有键 |
|
|
assertArrayNotHasKey |
断言没有键 |
|
|
assertContains |
断言包含 |
|
|
assertNotContains |
断言不包含 |
|
|
assertContainsOnly |
断言只包含 |
|
|
assertNotContainsOnly |
断言不只包含 |
|
|
对象类型
方法名 |
含义 |
参数 |
返回值 |
---|---|---|---|
assertAttributeContains |
断言属性包含 |
|
|
assertAttributeContainsOnly |
断言属性只包含 |
|
|
assertAttributeEquals |
断言属性等于 |
|
|
assertAttributeGreaterThan |
断言属性大于 |
|
|
assertAttributeGreaterThanOrEqual |
断言属性大于等于 |
|
|
assertAttributeLessThan |
断言属性小于 |
|
|
assertAttributeLessThanOrEqual |
断言属性小于等于 |
|
|
assertAttributeNotContains |
断言不包含 |
|
|
assertAttributeNotContainsOnly |
断言属性不只包含 |
|
|
assertAttributeNotEquals |
断言属性不等于 |
|
|
assertAttributeNotSame |
断言属性不相同 |
|
|
assertAttributeSame |
断言属性相同 |
|
|
assertSame |
断言类型和值都相同 |
|
|
assertNotSame |
断言类型或值不相同 |
|
|
assertObjectHasAttribute |
断言对象有某属性 |
|
|
assertObjectNotHasAttribute |
断言对象没有某属性 |
|
|
class类型
方法名 |
含义 |
参数 |
返回值 |
---|---|---|---|
assertClassHasAttribute |
断言类有某属性 |
|
|
assertClassHasStaticAttribute |
断言类有某静态属性 |
|
|
assertClassNotHasAttribute |
断言类没有某属性 |
|
|
assertClassNotHasStaticAttribute |
断言类没有某静态属性 |
|
|
文件相关
方法名 |
含义 |
参数 |
返回值 |
---|---|---|---|
assertFileEquals |
断言文件内容等于 |
|
|
assertFileExists |
断言文件存在 |
|
|
assertFileNotEquals |
断言文件内容不等于 |
|
|
assertFileNotExists |
断言文件不存在 |
|
|
XML相关
方法名 |
含义 |
参数 |
返回值 |
---|---|---|---|
assertXmlFileEqualsXmlFile |
断言XML文件内容相等 |
|
|
assertXmlFileNotEqualsXmlFile |
断言XML文件内容不相等 |
|
|
assertXmlStringEqualsXmlFile |
断言XML字符串等于XML文件内容 |
|
|
assertXmlStringEqualsXmlString |
断言XML字符串相等 |
|
|
assertXmlStringNotEqualsXmlFile |
断言XML字符串不等于XML文件内容 |
|
|
assertXmlStringNotEqualsXmlString |
断言XML字符串不相等 |
|
|
也可以通过查看vendor\phpunit\phpunit\src\Framework\Assert.php 文件实现的所有方法
基镜
在编写测试时,最费时的部分之一是编写代码来将整个场景设置成某个已知的状态,并在测试结束后将其复原到初始状态。这个已知的状态称为测试的 基境(fixture)。
例如在User测试中,我们每次都需要new User进行测试user类,其实我们完全可以使用基镜:
<?php
/**
* Created by PhpStorm.
* User: Tioncico
* Date: 2019/4/2 0002
* Time: 10:53
*/
use PHPUnit\Framework\TestCase;
include "User.php";//引入User类,可使用自动加载省略这步
class UserTest extends TestCase
{
protected $user;
function setUp()
{
parent::setUp(); // TODO: Change the autogenerated stub
$this->user = new User();
//例如这个类有很多属性需要自定义,初始化,都可以在这里完成
//例如这个类需要查找数据库进行赋值,都可以在这里完成
//例如需要新增一条数据用于测试,都可以在这里完成
}
function tearDown()
{
parent::tearDown(); // TODO: Change the autogenerated stub
unset($this->user);//销毁类属性,都可以在这里调用
//例如测试完需要把数据还原回之前的状态,可以在这里完成
//例如测试完需要把数据删除,可以在这里完成
}
public function testGet()
{
$user = $this->user;
$data= $user->get(1);
$this->assertEquals('1',$data['id']);//断言返回的id为1
}
public function testAdd()
{
$user = $this->user;
$data = [
'id'=>1,
'name'=>'tioncico'
];
$this->assertEquals($data,$user->add($data));//断言传入data返回data
$this->assertFalse($user->add([]));//断言传入空数组返回false
}
public function testDelete()
{
$user = $this->user;
$data= $user->delete(1);
$this->assertTrue($data);//断言返回true
}
}
复制
继承
phpunit的测试用例都可以直接继承,进行多继承测试
例如我们需要编写/Admin/Index/index /Admin/User/index.....等等,位于Admin模块下的所有控制器,我们可以先编写一个admin测试基类:
<?php
/**
* Created by PhpStorm.
* User: Tioncico
* Date: 2019/4/2 0002
* Time: 11:10
*/
use PHPUnit\Framework\TestCase;
class AdminBase extends TestCase
{
protected $session;//测试admin模块的控制器时,都是需要登录的,每次请求接口都需要一个登陆标识
function setUp()
{
parent::setUp(); // TODO: Change the autogenerated stub
$this->login();
}
function tearDown()
{
parent::tearDown(); // TODO: Change the autogenerated stub
$this->logout();
}
/**
* 登陆逻辑
* login
* @author Tioncico
* Time: 11:11
*/
function login(){
//这里需要调用后台的登陆接口,进行登陆,并把session赋值到$this->session
$this->session='测试session';
}
/**
* 退出逻辑
* logout
* @author Tioncico
* Time: 11:11
*/
function logout(){
//这里需要通过$this->session去调用退出接口,这样就退出了一次测试
}
}
复制
这样,我们所有关于admin模块的测试用例,都可以继承该类进行测试,每次测试时,都会调用该基类的登陆进行登陆,并将session赋值,我们只需要直接$this->session取出即可调用测试
额外的方法
在这里需要注意的是:
只有类名为xxTest和方法名为testxx的才是测试例子,在有的时候,我们可以写更多的方法用于给测试方法调用,而在运行测试用例的时候并不会调用到该方法,例如上面的adminBase 的login logout方法,直接运行测试的时候不会直接被调用.
多参数测试(数据供给器)
我们可以通过在注释增加数据供给器方法名,进行给测试用例增加参数测试,例如我们需要测试User类的add方法:
<?php
/**
* Created by PhpStorm.
* User: Tioncico
* Date: 2019/4/2 0002
* Time: 10:51
*/
class User
{
function add($data){
if ($data['id']<=0){
return false;
}
if (strlen($data['name'])<=5){
return false;
}
if ($data['age']>190||$data['age']<10){
return false;
}
return $data;
}
}
复制
测试用例:
<?php
/**
* Created by PhpStorm.
* User: Tioncico
* Date: 2019/4/2 0002
* Time: 10:53
*/
use PHPUnit\Framework\TestCase;
include "User.php";//引入User类,可使用自动加载省略这步
class UserTest extends TestCase
{
protected $user;
function setUp()
{
parent::setUp(); // TODO: Change the autogenerated stub
$this->user = new User();
//例如这个类有很多属性需要自定义,初始化,都可以在这里完成
//例如这个类需要查找数据库进行赋值,都可以在这里完成
//例如需要新增一条数据用于测试,都可以在这里完成
}
function tearDown()
{
parent::tearDown(); // TODO: Change the autogenerated stub
unset($this->user);//销毁类属性,都可以在这里调用
//例如测试完需要把数据还原回之前的状态,可以在这里完成
//例如测试完需要把数据删除,可以在这里完成
}
/**
* @dataProvider addData
* testAdd
* @param $id
* @param $name
* @param $age
* @author Tioncico
* Time: 11:20
*/
public function testAdd($id,$name,$age)
{
$user = $this->user;
$data = [
'id'=>$id,
'name'=>$name,
'age'=>$age,
];
$this->assertFalse($user->add($data));//断言传入以上所有参数都返回false
}
function addData(){
return [
[0, 'name123', 18],//id不能为0
[-1, 'name123', 18],//id不能小于0
[99, 'name', 18],//name长度不够
[1, '', 18],//name为空
[1, null, 18],//name为null
[1, 'name123', 500],//年龄太大
];
}
}
复制
这样既可一次性测试多种错误判断的情况
详细的数据供给器可查看:phpunit数据供给器
phpstorm使用phpunit测试
只需要根据图示,点击+号,然后根据安装的方式(composer,phar等)进行配置既可
新增测试用例:
运行测试用例:
测试结果大概如下:
当你的项目有改动的时候,都可以直接运行测试用例,来测试你的改动是否影响了其他地方,非常方便
- 点赞
- 收藏
- 关注作者
评论(0)