PHPUnit安装
1. composer require --dev phpunit/phpunit
执行这个命令之后可检查两处:
composer.json 文件中增加了如下的依赖,并且composer自动加载的相关文件都更新了
{
"require-dev": {
"phpunit/phpunit": "^7.0"
}
}
vendor
目录中增加了phpunit/phpunit
相关的文件夹
2. 利用composer的自动加载机制,引入测试代码在项目中的加载
{
"autoload": {
"psr-4": {
"Tests\\": "tests/"
}
}
}
3. 配置PHPStorm
如下图:Settings
> Languages & Frameworks
> PHP
> Test Frameworks
确保单元测试框架加载了本项目的 vendor/autoload.php
文件
快速上手
1. 在 tests
文件夹新增 ExampleTest.php
文件,内容如下
<?php
namespace tests;
class ExampleTest extends \PHPUnit\Framework\TestCase
{
public function testBasicTest()
{
$this->assertTrue(true);
}
}
2. 快速运行当前测试文件的快捷键是 Ctrl + Shift + F10
如果这组快捷键在你的IDE无效,亦可点击要测试的方法名字,右键 选中 执行 Run 'testBasicTest'
操作
3. 对的,就是如此简单!
按照第二步的操作我们可以看到IDE底部会输出单元测试的结果日志,特别的,你看到了ok
就代表我们的测试通过了。
单元测试到底能干啥?
本篇的重点不是来宣讲单元测试的重要性的问题,因为这个答案是肯定的是毋容置疑的,如果非要提这个问题:
1、编写测试用例,帮助我们更好的梳理业务代码的组织形式,比如我们和前端预定了字段和返回形式,就可以根据接口定义断言我们的返回,提高系统健壮性;
2、利用单元测试定义检验系统单一代码块是否符合预期,方便以后能够放心大胆的做重构,只要我们的用例能够通过;
3、测试覆盖率是衡量软件质量的重要标准之一;
4、为落地DevOps打基础,代码交付速度提升也增加了代码风险,利用单元测试在持续集成阶段就能自动检验是否有代码bug影响旧逻辑,方便更快更好的交付软件;
除此之外,不再过多照本宣科的讲解单元测试相关,我们把重点还是放在如何落地到项目中。
系统引入单元测试
比如我想测试 sdk
下一系列 Service
文件,我在 tests
目录下创建了一个 services
目录,然后新增一个 H5payTest.php
文件,如你所见,单元测试的文件名后缀要以Test结尾
<?php
namespace tests\services;
class H5payTest extends \PHPUnit\Framework\TestCase
{
}
我们先写一部分代码把要测试逻辑放进去
<?php
namespace tests\services;
use sdk\services\H5payService;
class H5payTest extends \PHPUnit\Framework\TestCase
{
private $service;
public function testWx()
{
// 我先尝试把我需要测试的类引进来,然后运行
$this->service = new H5payService();
$this->assertNotEmpty(1);
}
}
运行结果
Error : Class 'sdk\services\H5payService' not found
,咦?我需要的类找不到?加载不进来怎么办?这个主要是因为我们的sdk的类文件都依赖 sdk/Autoload.php 这个文件去查找的。但是在这里测试怎么能 require 进来?
PHPStorm也提供了配置的方法,就是运行单元测试前要执行启动脚本,我们新增文件 tests/bootstrap.php
文件内容参考如下
<?php
date_default_timezone_set('Asia/Shanghai');
define("SDK_PATH", __DIR__ . '/../sdk/');
define("CONFIG_PATH", __DIR__ . '/../config/');
define('CONFIG_FILE', __DIR__ . '/../config_map/your-config.php');
define('PJNAME', __DIR__ . 'yourname');
require_once SDK_PATH . 'Autoload.php';
然后把路径在下面的配置中选中
然后 Ctrl + Shift + F10
运行
这下就可以了,示例的代码如下,每个待测试的方法 test 开头
<?php
namespace tests\services;
use sdk\services\H5payService;
class H5payTest extends \PHPUnit\Framework\TestCase
{
private $service;
public function __construct()
{
parent::__construct();
$this->service = new H5payService();
}
public function testWx()
{
$params = [
'agent_id' => 11111103,
'merchant_id' => 'C555555550670592',
'pay_type' => 'WX',
'order_id' => '11111111' . rand(11111, 99999),
'price' => '1',
'body' => 'h5支付',
'client_ip' => '127.0.0.1',
'open_id' => 'ohTKdw6446494946464yKyR5s',
'sub_appid' => 'wx136161316494946fa59'
];
$result = $this->service->deal($params);
$this->assertIsArray($result);
$this->assertArrayHasKey('open_id', $result);
$this->assertArrayHasKey('jsapi', $result);
$this->assertArrayHasKey('plat_orderid', $result);
$this->assertNotEmpty($result['open_id']);
$this->assertNotEmpty($result['jsapi']);
$this->assertNotEmpty($result['plat_orderid']);
}
public function testZfb()
{
$params = [
'agent_id' => 1011113,
'merchant_id' => 'C96669959669666695592',
'pay_type' => 'ZFB',
'order_id' => '11111111' . rand(11111, 99999),
'price' => '1',
'open_id' => '2343243434',
'body' => 'h5支付',
'client_ip' => '127.0.0.1',
];
$result = $this->service->deal($params);
$this->assertIsArray($result);
}
}
如何组织用例
一般一个功能集分在一个文件,多个测试方法分别测试不同的代码块,单元测试的关键就是利用”断言” assrrt系列方法判断返回结果是否符合预期。PHPUnit还有一些相对好用的方法帮我们组织数据,在官方文档简单明了。
1 项目根目录新增文件 phpunit.xml
<phpunit bootstrap="src/your-project-boot-file.php">
<testsuites>
<testsuite name="money">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
2 在项目根目录执行 phpunit
它将在递归遍历 tests 时添加所有在 Test.php 文件中找到的 Test 类
3 测试报告
https://phpunit.de/manual/6.5/zh_cn/logging.html