原创

关于项目中的单元测试

温馨提示:
本文最后更新于 2021年06月02日,已超过 1,031 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我

本文将使用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

正文到此结束
本文目录