一、什么是白盒测试
白盒测试是一种测试策略,这种策略允许我们检查程序的内部结构,对程序的逻辑结构进行检查,从中获取测试数据。白盒测试的对象基本是源程序,所以它又称为结构测试或逻辑驱动测试,白盒测试方法一般分为静态测试和动态测试。
二、如何去做白盒测试
网上很多介绍白盒测试的文章会提到白盒测试的方法有:代码检查法、静态结构分析法、静态质量度量法、逻辑覆盖法、基本路径测试法、路径覆盖等等。实际工作中的白盒测试并不是一上来就进行代码分析,我个人理解白盒测试应该从以下几个步骤来一步一步执行:
1、使用静态代码分析工具:Findbugs先找出一些简单的 bug
- 操作空对象;
- 数组访问越界;
- 线程安全;
- 字符串拼接;
- 资源关闭;
2、diff评估影响范围,找边界和影响范围
- 往上找,找它的调用链,找测试范围的边界;
- 往下找,找它对下游的影响,找影响范围;
3、做单测,从上往下串
- 不只是对改动方法做单测;
- 还要找到它影响的点,从上到下往下串;
4、单独拉分支,梳理代码逻辑
- checkpoint:根据checkpoint画出流程图/时序图,后面做接口测试的测试点/检查点;
- bug:梳理代码时能够确定的问题;
5、接口测试
- 基于第四步代码梳理的checkpoint来做接口测试;
- 只做白盒测试不做接口测试,无法将代码的整个逻辑理顺;
6、debug再做一遍
- 远程debug,将整个流程走一遍;
另外,对于接口测试和白盒测试,有些公司会引入代码覆盖率工具来衡量测试用例对代码的覆盖率,关于这一点我们将在其他文章中做详细介绍。
常用的代码覆盖率工具有:
- Cobertura
- EclEmma
- Jacoco
三、接口测试的策略
看过有些介绍接口测试的文档,核心思想就是根据接口文档,构造不同的参数组合,各种正常/异常的参数,然后组装请求发送服务端,最后进行返回结果的判断。这可能是很多测试同学认知的接口测试,我们不能说这么做是错的,但是,如果我们只是这样来做接口测试,对于线上系统来说有着极大的风险,因为随着业务的越来越复杂,很多测试点是接口文档所描述不到的。
在上面描述白盒测试的步骤时我们说到会根据代码梳理的结果来画出流程图/时序图,然后根据时序图上的各个点来构造各种正常/异常的测试场景进行接口测试,这样才能更为完善的进行接口测试,减小线上的风险。
什么是时序图:
时序图(Sequence Diagram),亦称为序列图、循序图,它通过描述对象之间发送消息的时间顺序显示多个对象之间的动态协作,可以直观的传达系统内外之间的交互过程。我们可以简单的举个例子:
- 程序从入口进来,先做了什么逻辑判断和处理;
- 处理完成后进行入库,入库的数据是什么,关键的状态是什么;
- 入库的数据哪些字段是我们要去检查的,状态是如何变更的;
- 缓存的key是什么,缓存失败的策略又是什么;
如何设计接口测试
我们以下面这个微信扫描二维码支付为例来说明:
发起支付请求
- 构造相同订单,基于并发或者多线程请求被测服务;
- 超时;
- 其他异常;
微信Server回调Pay接口生成预支付订单
- 回调多次,是否能保证只生成一笔订单
- 回调失败,内部又如何处理
- 返回未知异常
- 返回已知异常
调用微信下单接口提交预支付订单
- 调用失败,如何处理
- 预支付订单不存在
- 预支付订单过期
确认订单
- 密码正确
- 密码不正确
返回订单详情
- 订单不存在
未收到支付状态
- 查询不到结果
- 查询到支付中/支付成功/支付失败
通过以上分析可以看出,为什么我们说做接口测试一定要先把代码的逻辑梳理清楚。如果我们只从接口文档的描述来做接口测试,我们对这些后台处理逻辑不清楚,那么这些测试点就会被遗漏,把所有风险都遗留到了线上。
四、接口自动化测试
1、分析功能及接口的优先级别
在谈到自动化测试的时候,很多同学上来就说:我们使用 Python + UnitTest/Java + Junit,使用了什么什么技术,使用了什么什么框架。但是在我们考虑实施之前,首先应该明确自动化测试的目标,可以从以下几个维度考虑:
- 功能维度
- 支付
- 代收
- 代付
- 开户...
- 这些功能包括的接口有哪些,条用顺序是什么样的,具体的执行流程又是什么样的
- 业务维度
- 核心业务
- 流量维度
- 百万级别
- 千万级别
- 风险维度
- 资金风险:出金、入金
- 黄金流程维度
- 核心业务流程
我们需要从以上五个方面去考虑需要做接口自动化测试的接口有哪些,然后就能够梳理出各接口及业务的的级别(P0/P1/P2)。
2、自动化策略
基于以上分析,我们就定义接口测试的策略,是要做单接口的还是模块级甚至是系统级的接口测试,又或者是这三者都要做。
- 场景级 --> 单接口
- 模块级 --> 只在模块内,预下单->提交订单->确认支付
- 系统级 --> 整个业务流程->订单->支付->网关->回调
3、定义自动化达成目标
定义好自动化测试的策略后,然后需要定义自动化测试要达成的目标。例如:
- 核心接口覆盖率 达到 50%
- 黄金流程覆盖率, normal级别case, 场景级40%, 模块30%,系统 30%
- 出金业务, 100% normal级覆盖
- 入金, 60% normal级覆盖
4、框架建设
基本诉求
- case规范要求
- case量级, 预估, 2000多条.
- 现状: 系统变更频繁程度, 业务接入的快慢程度, 当前资源投入情况. 变更的倾向性
实现
- common + env --> 工具 + 环境
- dao + client --> MySQL、Redis、Dubbo、Http
- core(extension) --> 测试用例能力扩展,执行前,执行后,参数处理等
- gen --> 自动生成代码
- manager -- > case管理, 报告输出等等
case模板
- 1.clean db,
- 2.db init(user_info)|= redis init |= Hive, Hbase,
- 3.mock client add
- 4.build request param
- 5.send request(Dubbo|Http,Thrift, RPC), RetMsg. 1000,2000,
- sendRequestForSuccess()
- 6.response assert,(errNo=200,)
- 7.db assert|redis assert.
- AccountDao().of().query(ColumnHolder.of().addColumn(order_id,111))
- ColumnHolder.getColumn("amount");
- Assert.assertEquals(ColumnHolder.getColumn("amount"),100)
- AccountDaoAssert.assertEquals("amount","200")
- 8.log assert(weak)
- 9.db clean
五、分库分表关注点
- 表的数量:2的幂指数;
- 字段的选择:
- 一般基于单个字段去分,也有少数情况是基于多个字段;
- 一般基于索引字段;
- 能够让请求均分到各张表,如:按 OrderID 划分比较合理,按 MerchID 划分就不太合理,会使一个商户的所有数据都在同一张表;
- 分库分表后的查询:插入和取出逻辑一致;