关于项目中的单元测试
本文将使用phpunit组件和easyswoole后端代码进行说明
什么是单元测试
什么是单元测试?
单元测试是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等
在php api中,可以认为是对一个接口的整个功能进行测试.
例如:
正常登陆接口,将是长这样:
/**
* @Api(name="login",path="/Api/Admin/Auth/login")
* @ApiDescription("管理员登录")
* @Param(name="adminAccount",required="",description="密码")
* @Param(name="adminPassword",required="",description="账号")
* @ApiRequestExample("curl http://127.0.0.1:9501/Api/Admin/Auth/login?account=123456&password=e10adc3949ba59abbe56e057f20f883e")
* @ApiSuccess({"code":200,"result":{"adminId":1,"adminName":"zyx","adminAccount":"123456","addTime":0,"lastLoginTime":1596530015,"lastLoginIp":"192.168.0.122","adminSession":"b2187eb9f20fb327"},"msg":"登陆信息"})
* @author xdd
* Time: 16:03
*/
function login($adminAccount, $adminPassword)
{
$admin = AdminUser::create()->where(['adminAccount' => $adminAccount, 'adminPassword' => AdminUser::hashPassword($adminPassword)])->get();
if (!$admin){
$this->writeJson(Status::CODE_BAD_REQUEST,null,"账号或密码错误");
return;
}
$time = time();
$session = Random::character(32);
$admin->update([
'lastLoginTime' => $time,
'lastLoginIp' => $this->clientRealIP(),
'adminSession' => $session
]);
$this->response()->setCookie(self::ADMIN_TOKEN_NAME, $session, time() + 86400 * 7, '/');
$this->writeJson(Status::CODE_OK, $admin, "登陆信息");
}
主要功能如下:
验证账号密码,写入session token,返回登陆信息.
那我们的单元测试则为:
$userData = [
'adminAccount' => 'zxc',
'adminPassword' => '123456'
];
$response = $this->request('login', $userData,'Auth');//请求Auth控制器的login方法
$this->assertTrue(!!$response->result->adminSession);//断言一定会返回adminSession
单元测试编写完成
单元测试和一般测试的区别
看到上面,你可能会出现这样的想法:"这样测试跟我直接使用postman请求有区别吗?"
答案是,有也没有
单元测试本身就是在模拟调用某个接口,判断此接口返回数据是否符合预期,但是,单元测试可一次写完,批量调用,而postman还需要人工判断接口请求的数据返回是否正确
例如,当你全站有上千个接口,通过单元测试,可直接点击运行,直接测试上千个,而人工postman请求,需要自己判断上千个接口.
我只测试我自己新加的接口不行吗?为什么还得测试原来已经测试通过的?
如果你新加的接口不小心改动了其他接口相关的表,或者相关的公用方法,你测试新加的接口可以通过,但是旧的接口将会出现问题,影响整个系统的健壮性
所以,单元测试,可以测试到整个系统是否都在符合预期的情况下运行
数据mock
数据mock是指模拟数据,例如我们在单元测试中需要去请求第三方支付,或者需要借助第三方完成一些功能,或者需要在数据库修改数据,如果我们单元测试直接请求第三方是不太现实的,我们可以通过数据模拟的方式,去略过第三方操作,直接当第三方操作成功给我们已经返回了数据.
这个在php接口的单元测试中比较少见,因为php的代码都是直接操作数据库,没有使用serviceinterface层进行注入新的mock层进行模拟数据
完善的单元测试
本人认为,完善的单元测试需要有以下功能:
1:测试正常执行的返回是否符合预期,例如登陆接口,正常登陆接口将会是登陆成功,返回token
2:测试接口判断异常时候系统的错误返回是否符合预期,例如如果输错了账号密码,系统将会返回 "账号密码错误"
3:使用数据mock,尽量不要请求第三方服务,尽量不要修改数据库
4:如果需要使用数据库,在执行单元测试前,需要增加单元测试需要的数据,在执行单元测试后,尽量删除原有的测试数据,例如测试登陆,需要先新增一个测试用户,然后测试完成之后删除
5:测试数据边界,例如在修改年龄接口中,如果填入 -1,-100,2^64,-2^64,填中文,填特殊字符串 ,接口是否会出现预期之外的问题
6:测试每一个逻辑点,例如 申请添加好友接口,正常接口会判断好友是否存在,是否已经是其好友,是否已经存在此申请,是否已经被拉黑,我们需要生成不同的测试数据,测试到每一个逻辑点,断言是否符合预期
当然,越完善的单元测试,需要更多的精力,为了节约成本,可以只考虑1,5,6 点
实战单元测试
本人项目采用 php-curl组件进行发起http请求,测试已开启服务的接口.大致流程如下:
具体单元测试源码学习,可参考https://github.com/tioncico/newProject/tree/master/UnitTest
- 本文标签: 服务架构
- 本文链接: https://www.php20.cn/article/294
- 版权声明: 本文由仙士可原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权